cell2mat in a for loop

Hello,
I am trying to use the cell2mat in a for loop in order to convert my cell array in a double array. The code looks like the one below:
for j=1:length(j)
for ii=1:lentgh(A)
y = constants*A(ii) + constants*A(ii)*B(j) %my equation
end
pos{j,ii} = find(y >= 0, 1); %find the first position of y that crosses the zero
zero = cell2mat(pos); %convert the cell array into a normal array (double in this case since I am varying 2 parameters)
C_new = C(zero); %find the corresponding values at that position
end
The reason why I am using pos as a cell array is because by using a normal array, the code gives me error (because the values in the equation are too small, in fact the first cell of the array are empty) but I don't want my values to get overwritten. In the end, I should obtain a jxii matrix for zero (and for C_new as well).
How can I solve this problem?

10 Comments

Hi,
length(j) will always be equal to 1 and your j loop will run only once. Is that what you want to do?
That looks like you are avoiding the problem, instead of solving it. What should happen if you have no value that satisfies your condition? Should a 0 be inserted in your resulting matrix? Should it be a NaN? Should the original value be kept? If you want the zero matrix to be a double array, you should think about how to fill missing values. You should also move that out of your loop:
for j=1:length(j)
for ii=1:lentgh(A)
y = constants*A(ii) + constants*A(ii)*B(j) %my equation
end
pos{j,ii} = find(y >= 0, 1); %find the first position of y that crosses the zero
if isempty(pos{j,ii})
%fill with something, e.g. a NaN
pos{j,ii}=NaN;
end
end
zero = cell2mat(pos); %convert the cell array into a normal array (2D in this case since I am varying 2 parameters)
%here you need to separate the cases of NaN and not NaN, use the isnan function
C_new = C(zero); %find the corresponding values at that position
no, the lentgh of j is 10 and ii is 1000 (at the moment), so I should obtain in the end a 10x1000 matrix for zero and C_new (of course, minus the number of empty elements)
Arrays in Matlab are rectangular, so you can't have empty places. In this regard a cell array is a special case, since it is rectangular, but the contents of each element could be an empty array.
So you can get a 10x1000, but not minus the empty elements.
Also, you made a typo for length, and you should use numel if you want to go over every element (and size with a second input if you want to go over the elements of a specific dimension).
for jj=1:numel(B)
for ii=1:numel(A)
y = constants*A(ii) + constants*A(ii)*B(jj) %my equation
end
pos{jj,ii} = find(y >= 0, 1); %find the first position of y that crosses the zero
if isempty(pos{jj,ii})
%fill with something, e.g. a NaN
pos{jj,ii}=NaN;
end
end
zero = cell2mat(pos); %convert the cell array into a normal array (2D in this case since I am varying 2 parameters)
%here you need to separate the cases of NaN and not NaN, use the isnan function
C_new = C(zero); %find the corresponding values at that position
When running the code, I get the following error:
Error using cat
Dimensions of arrays being concatenated are not consistent.
Error in cell2mat (line 78)
m = cat(1,m{:});
Something with cell2mat is not working when working with matrix rather than arrays?
There is probably at least one matrix in your cell array that has different dimensions than another matrix in the same row or column of that cell array. See cell2mat to understand the requirements that must be satisfied in order for this function to behave as expected.
Yes, you're right. Sorry my mistake.
The problem when putting the NaN value (or whichever value) on my array, I logically get the error "Array indices must be positive integers or logical values." when computing C_new = C(zero). That is why I wanted to avoid replacing the empty cells in the pos cell array. Any suggestion on how I can proceed?
As Rik said, you're just avoiding the problem by using a cell array. And of course, the problem comes back later.
With regards to "I logically get the error "Array indices must be positive integers or logical values." when computing C_new = C(zero).", that's easily worked around. However, we probably would be better off solving your initial problem properly. Unfortunately, it's really not clear what you're trying to do as there are several issue with your code:
1)
for j = 1:length(j)
As soon as that line is executed, the initial j (hopefully a vector) whose length has been calculated is replaced by a scalar value that is increased at each step.
2)
for ii=1:lentgh(A)
y = constants*A(ii) + constants*A(ii)*B(j) %my equation
end
Other than the mispelled length, that loop overwrite y at each steps. When the loop ends, y is simply the last value computed, so the whole lot is equivalent to:
y = constants*A(end) + constants*A(end)*B(j); %assuming A is a vector otherwise it's not the end index that is used
3) As a result of the previous issue, if constants is scalar, y will only have one element, so it's not clear why you then do a find(y>=0).
So can you explain what is it you're trying to do? Possibly, give some examples of the input.I suspect that the loops are not needed at all as well.
I think you should use something like that. Anyway, if you provide examples for A,B,C and what you expect for Cnew it will be easier
A = [1,2,3,4];
B = [1,2,3,4,5];
constant1 = 5;
constant2 = 5;
y = (A'*(constant1*ones(size(B)) + constant2*B))';
C = ones(size(y));
Cnew = C(y >= 0);
I am trying to find the zeros of a certain equation (i.e. the roots). I cannot use any matlab polynomial solver since it's not just a polynomial equation and the fsolve solver needs an initial value sufficiently far from zero (and my results have an order of magnitude around 10^-6).
So, at the beginning I have started making the loop on just one variable, in order to find the roots for each value on that, and that didn't gave me any problem (besides the empty cell in the cell array). I am using pos{ii} as a cell array in order to not overwrite the values generated from the loop (from the zeroes of the y equatiion). Then I would convert the cell array to a normal array simply with the command cell2mat.
When making a loop on another variable involved in the equation, things get more complicated (see problem explained on the above comments).

Sign in to comment.

Answers (1)

As I explained in point 2) of my comment, in the code you've posted, the ii loop does nothing useful and only the last step affects y. You still haven't explained properly what you're doing so it's difficult to give you a good solution to your problem. I also completely forgot to mention that with your given code,
pos{j, ii} = something;
is the same as
pos{j, length(A)} = something;
since the assignment is outside of the ii loop. And elements pos{j, 1:length(A)-1} will always be empty.
Instead, I'm just going to solve the immediate problem of "I logically get the error "Array indices must be positive integers or logical values." when computing C_new = C(zero)" as it's the best we can do.
%As pointed out, the loop code in the question makes absolutely no sense
%so making up some demo code. Adapt as required
A = 1:10;
B = 1:5;
x = linspace(0, 2*pi, 100);
C = x;
%algorithm
pos = nan(numel(A), numel(B)); %predeclare array
for col = 1:numel(B)
for row = 1:numel(A)
y = sin(x*A(row)) - cos(x*B(col)) - 2*mod(A(row)+B(col), 2); %some equation that will always be negative for some A and B
zerocross = find(y >= 0, 1);
if ~isempty(zerocross)
pos(row, col) = zerocross
end
end
end
%at this point we have pos, a matrix of indices with some NaN in it when there was no positive values in y
%we want a Cnew matrix which has C(pos) for the non NaN values:
Cnew = nan(size(pos));
Cnew(~isnan(pos)) = C(pos(~isnan(pos))); %only copy C values for which pos is non-nan.

Asked:

on 25 Feb 2019

Answered:

on 28 Feb 2019

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!