13 views (last 30 days)

I have function and the output of test function is cell. I want to write a 'for loop' to calulate 3 times iteration.

This is a code that I try.

A={[1;3;4],[2],[2;5]}

mo=3

log_Ime_Y=zeros(mo,size(A,2));

for i=1:mo

[Y] = Test(X); %function

Ime_Y= cellfun(@(n)angle(n),Y,'uni',0)

Real_Y= cellfun(@(n)abs(n),Y,'uni',0)

log_Ime_Y{mo,i}=Ime_Y{i}

log_Real_Y{mo,i}=Real_Y{i}

end

but it is not working

example for Y

Y in first iteration ={[1+2i;2+1i;3+4i],[4+1i],[5+4i,7+3i]}

Y in second iteration ={[2+3i;4+2i;5+4i],[6+1i],[6+4i,6+3i]}

Y in third iteration={[2+5i;4+3i;4+4i],[6+i],[6+4i,9+3i]};

Result:

log_Ime_Y={{[1.10;0.46;0.92],[0.24],[0.67,0.4]};

{[0.98;0.46;0.67],[0.16],[0.58,0.46]};

{[1.19;0.64;0.78],[0],[0.58,0.32]}}

I want to store log_Ime_Y

Guillaume
on 29 Jan 2019

Ok, now it's clearer what you want to do. I'm assuming that the number of cells and the size of each cell in Y, returned by Test is the same as A. It's not actually clear since in your example size(A{3}) is [2, 1] but size(Y{3} is [1, 2]. I assume it's a typo. I'm also assuming that the vectors in A are always column vectors.

For efficiency, it's probably best to store log_XXX_Y as a cell array of 2D matrices (columns correspond to mo). That means you can't use cellfun for calculating the angle and norm:

%inputs

A = {[1;3;4],[2],[2;5]};

mo = 3;

%preallocation of output cell arrays

log_Ime_Y = cellfun(@(x) zeros(numel(x), mo), A, 'UniformOutput', false);

log_Real_Y = log_Ime_Y;

%loop

for i = 1:mo

Y = Test(X); %different output on each call

for j = 1:numel(Y)

log_Ime_Y{j}(i, :) = angle(Y{j});

log_Real_Y{j}(i, :) = abs(Y{j});

end

end

%mean

mean_Ime_Y = cellfun(@(m) mean(m, 2), log_Ime_Y, 'UniformOutput', false);

mean_Real_Y = cellfun*@(m) mean(m, 2), log_Real_Y, 'UniformOutput', false);

Alternatively, you can store log_xxx_Y as a cell array of cell arrays as you show. You can use more cellfuns but it's probably going to be slower:

%inputs

A = {[1;3;4],[2],[2;5]};

mo = 3;

%preallocation of output cell arrays

log_Ime_Y = cell(1, mo);

log_Real_Y = cell(1, mo);

%loop

for i = 1:mo

Y = Test(X); %different output on each call

log_Ime_Y{mo} = cellfun(@(n) angle(n), Y, 'UniformOutput', false);

log_Real_Y{mo} = cellfun(@(n) abs(n), Y, 'UniformOutput', false);

end

%convert cell array of cell arrays into cell array of 2D matrices. Will fail if the vectors are not COLUMN vectors

log_ime_Y = cellfun(@horzcat, log_Ime_Y{:}, 'UniformOutput', false);

log_real_Y = cellfun(@horzcat, log_real_Y{:}, 'UniformOutput', false);

%calculate mean

mean_Ime_Y = cellfun(@(m) mean(m, 2), log_Ime_Y, 'UniformOutput', false);

mean_Real_Y = cellfun*@(m) mean(m, 2), log_Real_Y, 'UniformOutput', false);

Jan
on 29 Jan 2019

Edited: Jan
on 29 Jan 2019

The posted code works exactly as expected. You called cellfun with the 'UniformOutput' set to false. Then it replies a cell array for each element of the input cell. Finally you store these cells in the 3rd row of the output cell array log_Ime_Y.

Do you expect anything else? Then please explain what it is. We do not know where the data in the 1st and 2nd row are coming from - obviously from some code above.

By the way, you access the i.th output of the function only in each iteration. Is this wanted? I suggest to use simple for loops to process cells. cellfun is lean and looks nice, but as soon as its compactness confuses the programmer, it is a drawback to use it.

Guillaume
on 29 Jan 2019

It is unclear what you are trying to do, in particular since we don't know what X and Y are. We can assume that Y is a cell array but we don't know its size. Certainly, as Jan pointed out, your loop doesn't make much sense. Assuming that the Test function or the X variable do not have internal state (i.e. repeated call of Test(X) always return the same result and do not change X), then the loop can be rewritten as:

Y = Test(X);

Ime_Y = cellfun(@(n)angle(n),Y,'uni',0)

Real_Y = cellfun(@(n)abs(n),Y,'uni',0)

for i=1:mo

log_Ime_Y{mo,i}=Ime_Y{i} %will error if numel(Y) < mo

log_Real_Y{mo,i}=Real_Y{i}

end

Clearly, the loop doesn't do much and can be replaced by a straightforward copy:

Y = Test(X);

Ime_Y = cellfun(@(n)angle(n),Y,'uni',0)

Real_Y = cellfun(@(n)abs(n),Y,'uni',0)

log_IME_Y(mo, 1:mo) = Ime_Y(1:mo);

log_Real_Y(mo, 1:mo) = Real_Y(1:mo);

Whether or not that is what you meant to do, we don't know since you haven't said what the code is meant to do (and it's not commented).

Jan
on 29 Jan 2019

@Naime Ahmadi: "this part is not working" does not allow to understand, what you do instead. See this example:

k = 17 + x;

% This is not working

Now you cannot have any idea why I assume, that this is wrong and how I want this to be changed.

Opportunities for recent engineering grads.

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

Start Hunting!
## 0 Comments

Sign in to comment.