MATLAB Answers

## calculate iteration in cellfun

Naime

### Naime (view profile)

さんによって質問されました 2019 年 1 月 29 日

### Guillaume (view profile)

さんによって 回答されました 2019 年 1 月 29 日
Guillaume

### Guillaume (view profile)

さんの 回答が採用されました
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;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.58,0.32]}}
I want to store log_Ime_Y

#### 0 件のコメント

サインイン to comment.

## 2 件の回答 ### Guillaume (view profile)

2019 年 1 月 29 日
採用された回答

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;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;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);

#### 0 件のコメント

サインイン to comment.

2019 年 1 月 29 日

### Jan (view profile)

2019 年 1 月 29 日

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

### Guillaume (view profile)

2019 年 1 月 29 日
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

### Jan (view profile)

2019 年 1 月 29 日
@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.
Naime

### Naime (view profile)

2019 年 1 月 29 日
I have a random element in function so in every iteration Ime_Y= cellfun(@(n)angle(n),Y,'uni',0) and Real_Y= cellfun(@(n)abs(n),Y,'uni',0) is changing.
for example: in (iteration 1) Real_Y={[1.10;0.46;0.92],[0.24],[0.67,0.4]}
in(iteration 2) Real_Y={[0.98;0.46;0.67],[0.16],[0.58,0.46]}
in(iteration 3) Real_Y={[1.19;0.64;0.78],,[0.58,0.32]}
After this as I want to calculate mean, I need to store Real_Y in every iteration.
so I want this 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.58,0.32]} };
After that I want to find a mean according to below
{[(1.10+0.98+1.19)/3,(0.46+0.46+0.64)/3,(0.92+0.67+0.78)/3], [(0.24+0.16+0)/3],[(0.67+0.58+0.58)/3,(0.4+0.46+0.32)/3];
I try your code but have error

サインイン to comment.