Taking the mean of a 3D matrix

3 views (last 30 days)
Richard
Richard on 15 Jun 2014
Commented: Image Analyst on 9 Feb 2020
Hi all,
I want to take the mean of values that are over a certain threshold (lets say 150) for a 3D matrix (such as X(i,j,k).
I want them mean for each third dimension like this;
Mean of X(:,:,1) over 150 is Y
Mean of X(:,:,2) over 150 is Z
and so on
I want matlab to only consider the row and coloumn when taking the mean not the third dimension (take the mean of i and j that are over 150 and report for each kth dimension).
I've been trying for a long time, how do i do this??? Can anyone help?
Thanks in advance.

Answers (3)

Matt J
Matt J on 15 Jun 2014
Edited: Matt J on 15 Jun 2014
X(X<150)=nan;
nanmean(reshape(X,[],size(X,3)),1),

dpb
dpb on 15 Jun 2014
Couple of ways...if have Stat Toolbox, use nanmean
x=X; % just to not destroy original
x(x<150)=nan; % mark those not wanted
xmn=nanmean(x,3); % mean on 3rd dimension
Lacking the toolbox, just one or two more steps...
n=sum(isfinite(x),3); % get the number in each x,y
x(isnan(x))=0; % zeros won't count in the sum
xmn=mean(x,3); % mean on 3rd dimension
  2 Comments
Richard
Richard on 15 Jun 2014
I want the mean of all of the first and second dimension terms, not over the third. I want a single value for each 3rd dimension.
dpb
dpb on 15 Jun 2014
Edited: dpb on 16 Jun 2014
Oh, my misread, I guess...a different way than Matt's (not necessarily better :)).
zmn=squeeze(nanmean([nanmean(X,1)],2));

Sign in to comment.


Image Analyst
Image Analyst on 16 Jun 2014
No need for nan's - just threshold and use logical indexing:
onePlane = X(:, :, 1); % Extract one plane/slice.
allThePixelsOverThreshold = onePlane(onePlane > 150); % Threshold and extract into vector
Y = mean(allThePixelsOverThreshold) % Take mean of only those pixels > 150
onePlane = X(:, :, 2);
allThePixelsOverThreshold = onePlane(onePlane > 150);
Z = mean(allThePixelsOverThreshold)
  2 Comments
Raheema Al Karim Damani
Raheema Al Karim Damani on 9 Feb 2020
@ImageAnalyst
how can I convert this code into a for loop?
something like this?
for i = 1: nTimePoints_8871456
idx8871456 = pf_t8871456(:,:,:,i);
PixelsAbvZro = idx8871456(idx8871456 > 0);
mn_pft8871456 = mean(PixelsAbvZro);
end
but when i do this it is taking the mean across whole instead of each slice
Image Analyst
Image Analyst on 9 Feb 2020
Well maybe you could but anyone looking at the code would chastise you for making very difficult-to-follow code by using bizarre variable names. Like you're calling something idx8871456 and people will think it's an index (because it starts with idx) but it's NOT an index. Very deceptive. Plus you used i as a variable name which is not recommended. This code is not maintainable by you (months later) or anyone else in your company who might inherit the code from you.
Assuming nTimePoints_8871456 is the number of slices you want to do you can do this:
[rows, columns, numberOfSlices] = size(pf_t8871456)
lastSlice = min([nTimePoints_8871456, numberOfSlices]) % Don't let nTimePoints_8871456 be more than the number of slices.
for slice = 1 : lastSlice
thisSlice = pf_t8871456(:, :, slice);
indexesOfPositiveValues = thisSlice > 0;
sliceMeans = mean(thisSlice(indexesOfPositiveValues))
end
It's more robust than what you have plus it has some better variable names. Again, I'd choose more descriptive variable names than nTimePoints_8871456 and pf_t8871456.

Sign in to comment.

Community Treasure Hunt

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

Start Hunting!