I have a griddedInterpolant F and some of the input variables are in a cell array form. As an example, this is how I created the interpolant F:
[x,y,z] = ndgrid(-5:1:5);
t = x+y+z;
mycell = {x,y};
F = griddedInterpolant(mycell{:},z,t);
In reality, the size of the cell array mycell changes each time I run the code, and that's why I figured I have to use a cell array as an input. Now I'd like to call this function with the same input structure. When I have a single row for each input, everything works fine as in the following example:
testcell = {1,3};
F(testcell{:},5)
ans =
9
However, when I'd like the inputs in a vector form, the interpolant doesn't work and I get the following error:
testcell = {1,3; 2, 4};
F(testcell{:,:},[5;1])
Error using griddedInterpolant/subsref
Invalid arguments specified in evaluating the interpolant.
Because I don't know the dimensions (number of columns) in my actual cell array, I can not break testcell apart. What is the right way to use the interpolant F in this case? I could, of course, use a for loop but this approach might be very time consuming due to the large number of data that I have.
I got an answer to my problem in another forum. Apparently, this problem is solved just by slightly fixing how testcell is defined at the end as such:
testcell = {[1;2]; [3; 4]};
Related
In matlab, is it possible to make the iterative variable a cell array? is there a workaround? This is the code I ideally want, but throws errors:
dim={};
a=magic(5);
for dim{1}=1:5
for dim{2}=1:5
a(dim{:})=1; %aimed to be equivalent to a(dim{1},dim{2})=1;
end
end
for dim{1}=1:5
↑
Error: Invalid expression. When calling a function or indexing a variable, use
parentheses. Otherwise, check for mismatched delimiters.
I tested that you cannot have A(1), or A{1} or A.x as index variable. https://www.mathworks.com/help/matlab/ref/for.html doesn't explicitly prohibit that, but it doesn't allow it either.
After very slight changes on your code, this should achieve what you seem to want:
dim={};
a = magic(5);
for dim1=1:5
dim{1} = dim1;
for dim2=1:5
dim{2} = dim2;
a(dim{:})=1; %aimed to be equivalent to a(dim{1},dim{2})=1;
end
end
However, I believe the following is a slightly better solution keeping the spirit of "use a cell array to index in your array":
CV = combvec(1:5,1:5); % get all combinations from (1,1) to (5,5). 2x25 double array. This function is a part of deep learning toolbox. Alternatives are available.
CM = num2cell(CV); % 2x25 cell array. Each element is a single number.
for dim = CM
% dim is a 2x1 cell array, eg {2,3}.
a(dim{:}) = 1; % as above.
end
However, none of these are likely a good solution to the underlying problem.
I am trying to plot a CDF for my data, but I get the following error message:
Error using cdf (line 69) Not enough input arguments
My code:
data =cell(1,5);
for j=1:length(container)-7
data{j} = some_values;
cdfplot(data)
So data is a 1x5 cell while inside of it, the values are the following
1x14600double, 1x260double, 1x2222double, 1x3000double, 1x72double
I am expecting a separate line for each of the double arrays i.e. my cdf figure to have 5 lines.
But, the error message confuses me, since I definitely have passed data. Any ideas?
Edited: ok, I have misswritten instead of cdfplot(), I had cdf()... the problem stays the same
The problem was the lack of knowledge on how cells and figures work.
figure;
hold on;
cellfun(#cdfplot,data);
This code did the job :)
In addition to the OP's answer using cellfun, you can also solve this by adjusting how you access the cell array.
Key Idea: Access A with A{} versus A()
% MATLAB R2018b
% Sample data
A = {rand(1,14600) rand(1,260) rand(1,2222) rand(1,3000) rand(1,72)};
Notice that A(1) returns
ans = 1×1 cell array {1×14600 double}
while A{1} returns the full 1x14600 double array (extracts it completely from the cell array).
% Example usage
szA = size(A);
for k = 1:szA(2)
subplot(5,1,k)
cdfplot(A{k})
end
From this example you can see cdfplot works fine.
I am working on a code to extract my AR(1)-GARCH(1) parameter, which I estimated using an AR(1)-GJR(1,1) model to individual matrices so that I can use them as variables in my calculations. As I have 16 time series variables, I combine the code with a loop in the following way:
for i=1:nIndices
AA_ARCH(:,i) = cell2mat(fit{i}.Variance.ARCH)';
end;
My problem is that for some variables is are no for AA_ARCH(:,i) the dimension is lower than nIndices. Naturally, when I try to export the estimates in the loop which specified the dimension of (:,i) and nIndices matlab reports a dimension mismatch. I would like to tell Matlab to replace the NaN with 0 instead of leaving the spot empty so that it is able to produce a (1,nIndices) matrix from AA_ARCH.
I thought of something like the this:
fit{i}.Variance.Leverage(isnan(fit{i}.Variance.Leverage))=0
but I wasn't able to combine this part with the previous code.
I would be very happy about any hints!
Best, Carolin
UPDATE:
Here is a fully a runnable version of my code which produces my problem. Notice that the code produces a dimension mismatch error because there is no ARCH and GARCH estimate in the fit.gjr(1,1) for time series 1. For these missing values I would like to have 0 as a placeholder in the extracted matrix.
returns = randn(2,750)';
T = size(returns,1);
nIndices = 2;
model = arima('AR', NaN, 'Variance', gjr(1,1));
residuals = NaN(T, nIndices);
variances = NaN(T, nIndices);
fit = cell(nIndices,1);
options = optimset('fmincon');
options = optimset(options, 'Display' , 'off', 'Diagnostics', 'off', ...
'Algorithm', 'sqp', 'TolCon' , 1e-7);
for i = 1:nIndices
fit{i} = estimate(model, returns(:,i), 'print', false, 'options', options);
[residuals(:,i), variances(:,i)] = infer(fit{i}, returns(:,i));
end
for i=1:nIndices
AA_beta(:,i) = cell2mat(fit{i}.AR)';
AA_GARCH(:,i) = cell2mat(fit{i}.Variance.GARCH)';
AA_ARCH(:,i) = cell2mat(fit{i}.Variance.ARCH)';
AA_Leverage(:,i) = cell2mat(fit{i}.Variance.Leverage)';
end;
I have some general things to say about the code, but first a solution to your problem:
You can put a simple if/else structure in your loop to handle the case of an empty array:
for ind1=1:nIndices
AA_beta(:,ind1) = cell2mat(fit{ind1}.AR)'; %//'
%// GARCH
if isempty(cell2mat(fit{ind1}.Variance.GARCH)') %//'
AA_GARCH(1,ind1) = 0;
else
AA_GARCH(:,ind1) = cell2mat(fit{ind1}.Variance.GARCH)'; %//'
end
%// ARCH (same exact code, should probably be exported to a function)
if isempty(cell2mat(fit{ind1}.Variance.ARCH)') %//'
AA_ARCH(1,ind1) = 0;
else
AA_ARCH(:,ind1) = cell2mat(fit{ind1}.Variance.ARCH)'; %//'
end
AA_Leverage(:,ind1) = cell2mat(fit{ind1}.Variance.Leverage)'; %//'
end;
Side note: I initially tried something like this: soz = #(A)isempty(A)*0+~isempty(A)*A; as an inline replacement for the if/else, but it turns out that MATLAB doesn't handle [] + 0 the way I wanted (it results in [] instead of 0; unlike other languages like JS).
As for the other things I have to say:
I am a firm supporter of the notion that one shouldn't use i,j as loop indices, as this may cause compatibility problems in some cases where complex numbers are involved (e.g. if you loop index is i then 1*i now refers to the loop index instead of to the square root of -1).
Part of your problem was that the arrays you were writing into weren't preallocated - which also means the correct datatype was unknown to MATLAB at the time of their creation. Besides the obvious performance hit this entails, it could also result in errors like the one you encountered here. If, for example, you used cells for AA_beta etc. then they could contain empty values, which you could later replace with whichever placeholder your heart desired using a combination of cellfun and isempty. Bottom line: lint (aka the colorful square on the top right of the editor window) is your friend - don't ignore it :)
I have the following piece of code:
for query = queryFiles
queryImage = imread(strcat('Queries/', query));
queryImage = im2single(rgb2gray(queryImage));
[qf,qd] = vl_covdet(queryImage, opts{:}) ;
for databaseEntry = databaseFiles
entryImage = imread(databaseEntry.name);
entryImage = im2single(rgb2gray(entryImage));
[df,dd] = vl_covdet(entryImage, opts{:}) ;
[matches, H] = matchFeatures(qf,qf,df,dd) ;
result = [result; query, databaseEntry, length(matches)];
end
end
It is my understanding that it should work as a Java/C++ for(query:queryFiles), however the query appears to be a copy of the queryFiles. How do I iterate through this vector normally?
I managed to sort the problem out. It was mainly to my MATLAB ignorance. I wasn't aware of cell arrays and that's the reason I had this problem. That and the required transposition.
From your code it appears that queryFiles is a numeric vector. Maybe it's a column vector? In that case you should convert it into a row:
for query = queryFiles.'
This is because the for loop in Matlab picks a column at each iteration. If your vector is a single column, it picks the whole vector in just one iteration.
In MATLAB, the for construct expects a row vector as input:
for ii = 1:5
will work (loops 5 times with ii = 1, 2, ...)
x = 1:5;
for ii = x
works the same way
However, when you have something other than a row vector, you would simply get a copy (or a column of data at a time).
To help you better, you need to tell us what the data type of queryFiles is. I am guessing it might be a cell array of strings since you are concatenating with a file path (look at fullfile function for the "right" way to do this). If so, then a "safe" approach is:
for ii = 1:numel(queryFiles)
query = queryFiles{ii}; % or queryFiles(ii)
It is often helpful to know what loop number you are in, and in this case ii provides that count for you. This approach is robust even when you don't know ahead of time what the shape of queryFiles is.
Here is how you can loop over all elements in queryFiles, this works for scalars, row vectors, column vectors and even high dimensional matrices:
for query = queryFiles(:)'
% Do stuff
end
Is queryFiles a cell array? The safest way to do this is to use an index:
for i = 1:numel(queryFiles)
query = queryFiles{i};
...
end
I was reading that in MatLab, if you are going to fill a larger matrix, its more computational efficient to declare it's size from before with the use of the cell command; E.g.
X = cell(500,90);
but when I try to add values to it, like
X(i;) = x
where i is vector of double of length 90, and i an integer, I get
conversion from cell to double is not possible
Is my understanding of the cell function correct?
Cell contents are being addressed using curly braces, for example:
X{1,1}=1:8;
cell command creates an empty array:
C = cell(3,4,2);
% Or alternatively:
C{3,4,2} = [];
What you do with the cell array is up to you. But most likely it is not what you want - see Rasman's comment.
Have a look at some more examples either at MathWorks or other tutorials.