average between cell arrays of doubles

Hello, I'm working with a nested cell array in which each original cell contains a nested cell array of doubles.
For simplicity, the original nested array could have 10 cell arrays within it. For each of those cell arrays, there are 100 doubles that are 30x50 in length. I would like to get the mean/average of all of those doubles such that they go from 100 instances of 30x50 doubles to just 1 single instance of 30x50 double.
This would result with the average value found in each element of the double across the instances. This would mean that the original cell array is now 10 cells, with each having only one instance of 30x50 double as their individual averages.
Please let me know if you need more information to help me with calculating the average. Thank you!

 Accepted Answer

C_mean = cellfun(@(c)mean(cat(3,c{:}),3),C,'UniformOutput',false);

5 Comments

Hello, thank you for your answer. So I can better understand how to do this going forward, why is the dimension 3 for the cat (and therefore also for mean)? Thank you.
As of right now, the line of code you provided me is not working because it says that "Brace indexing is not supported for variables of this type. However, as it is a cell I'm not sure what I should do differently. Here is my current code:
%preallocate C_mean
C_mean = cell(size(D,1),1);
for mtemp = 1:size(D,1)
c = D{mtemp,1};
% Vertically concatenate, pad with NaNs
maxNumCol = max(cellfun(@(c) size(c,2), c)); % max number of columns
%preallocate cMat
cMat = cell(size(c,1),1);
for padtemp = 1:size(c,1)
p = c(padtemp);
cMat{padtemp} = cell2mat(cellfun(@(p){padarray(p,[0,maxNumCol-size(p,2)],NaN,'Post')}, p)');
end %padtemp
pause
%calculate mean
C_mean=cellfun(@(cMat)mean(cat(3,cMat{:}),3,'omitnan'),cMat,'UniformOutput',false);
end %mtemp
Is D the cell array you described in the question?
% create random D
% 1-by-10 cell array, each cell containing a 1-by-100 cell array,
% each cell of that containing a 30x50 double matrix
D = cell(1,10);
for ii = 1:10
D{ii} = permute(num2cell(rand(30,50,100),[1 2]),[1 3 2]);
end
D
D = 1x10 cell array
{1x100 cell} {1x100 cell} {1x100 cell} {1x100 cell} {1x100 cell} {1x100 cell} {1x100 cell} {1x100 cell} {1x100 cell} {1x100 cell}
D{1}
ans = 1x100 cell array
Columns 1 through 10 {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} Columns 11 through 20 {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} Columns 21 through 30 {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} Columns 31 through 40 {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} Columns 41 through 50 {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} Columns 51 through 60 {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} Columns 61 through 70 {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} Columns 71 through 80 {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} Columns 81 through 90 {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} Columns 91 through 100 {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double}
D_mean = cellfun(@(c)mean(cat(3,c{:}),3,'omitnan'),D,'UniformOutput',false)
D_mean = 1x10 cell array
{30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double}
The cat(3,c{:}) is to concatenate the 100 30-by-50 matrices to form a 30x50x100 array. Then take the mean of that over the third dimension to end up with a 30-by-50 matrix representing the mean of all 100 30-by-50 matrices. And do that for each element of D by using cellfun.
Thank you for your explanation of why the dimension is 3. I'm not sure what I'm doing wrong using cellfun since that line of code won't work for me in my script. I'm left to assume its either 1. where I have cellfun trying to process in my for loop, or 2. what variable names I am placing into the cellfun line that is making it not work for me.
However, if I apply the same logic of the cellfun line of code to each individual cell array in 'D' (i.e., to use cat followed by mean before placing it into D_mean) it works! So the cellfun line of code must work if I would apply it correctly to my script. Thank you.
You're welcome!
It wasn't clear to me from your code whether D or cMat was the cell array you described in the question. (I guess D because each cell of cMat contains a matrix instead of a cell array.) If D is the relevant cell array, then the cellfun code from my answer should be placed after the mtemp loop, because it is intended to operate on a cell array of cell arrays. But it can't operate on D, since what you really want to operate on is a cell array that contains the padded versions of the contents of D, which is all values of cMat across all iterations of the mtemp loop, so you'd have to construct that - below I call it C. Something like this:
% create random D
% 10-by-1 cell array, each cell containing a 100-by-1 cell array,
% each cell of that containing a 30x50 double matrix
D = cell(10,1);
for ii = 1:10
D{ii} = permute(num2cell(rand(30,50,100),[1 2]),[3 1 2]);
end
%preallocate C
C = cell(size(D,1),1);
for mtemp = 1:size(D,1)
c = D{mtemp,1};
numCol = cellfun(@(x) size(x,2), c);
maxNumCol = max(numCol); % max number of columns
numColToAdd = maxNumCol-numCol;
%preallocate cMat
cMat = cell(size(c,1),1);
for padtemp = 1:size(c,1)
% pad with NaNs
cMat{padtemp} = padarray(c{padtemp},[0,numColToAdd(padtemp)],NaN,'Post');
end %padtemp
% pause
C{mtemp} = cMat;
end %mtemp
%calculate mean
C_mean=cellfun(@(c)mean(cat(3,c{:}),3,'omitnan'),C,'UniformOutput',false)
C_mean = 10x1 cell array
{30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double} {30x50 double}
I simplified the padding code because it's not necessary to use cell2mat and cellfun for that; since c{padtemp} is a matrix you can call padarray on it directly and store the result in a cell of cMat.
It's possible that code still may not work for you, in which case please save the variable D to a mat file and upload the mat file here and I'll take a look at it.

Sign in to comment.

More Answers (0)

Asked:

on 10 Jun 2024

Commented:

on 10 Jun 2024

Community Treasure Hunt

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

Start Hunting!