Having trouble finding the mean of array elements between two indices

8 views (last 30 days)
I'm getting a math error in a script I'm writing and haven't been able to figure out the problem. I'm trying to use a loop to calculate the mean of a group of array elements from one specific index to another.
totalReps = totalReps(~cellfun('isempty', totalReps'));
for i = 1:length(totalReps)
A = cell2mat(totalReps(i));
nzer(end + 1) = length(find(A));
end
repMeans = zeros(1, length(totalReps), 'single');
for i = 1:length(totalReps)
for j = int16(nzer(i) * 0.25):int16(nzer(i) * 0.75)
repMeans(i) = repMeans(i) + totalReps{i,1}(1,j);
end
repMeans(i) = repMeans(i) / (nzer(i) * 0.5);
end
totalReps is a N x 1 cell array composed of differently-sized 1 x N single-precision arrays. The purpose of this part of the script was to find the average of the middle 50% of the nonzero values in each element of totalReps. Every element of totalReps is some number of nonzero values followed by a number of zero values, so I used find() to create a parallel array nzer in order to index the nonzero elements. I then used a double for loop to add the middle 50% of each element into another parallel array repMeans. However after running the script, the elements of repMeans appear to all be off by around 1. If they are off by exactly 1 then it's easy enough to fix, but I'd like to understand what's going on.
I attached .xlsx files representing sample totalReps and corresponding repMean values.
Thanks in advance.
  2 Comments
Guillaume
Guillaume on 17 Oct 2019
Why is totalReps a cell array of vectors instead of a simple matrix (with NaNs for the shorter rows). Note that importing your example excel file would result in that matrix. Your whole code would be a lot simpler if it was a matrix.
Note that:
A = cell2mat(totalReps(i));
is simply:
A = totalReps{i};
Also note that:
length(find(A))
is simply:
nnz(A)
Any reason you're using single precision? And more importantly, why the pointless conversion to int16 (which matlab will immediately convert to double for indexing). If it's to make sure that the indices are integers, then use the proper function: round (assuming that's the rounding mode you meant to use instead of fix, ceil or floor, that's the one that int16 uses).
Also, don't use 2D indexing for vectors.
totalReps{i}(j)
is a lot simpler than totalReps{i, 1}(1, j) and doesn't leave the reader wondering if the cell array/matrix has more columns/rows.
Finally, why are you using a loop to calculate the mean instead of calling the mean function?
Daniel Hemphill
Daniel Hemphill on 17 Oct 2019
Thanks for your response, I updated the things you pointed out.
For your first question, I had trouble trying to figure out how to create a matrix with two unknown dimensions and settled on a cell array simply because it was the first solution I found. (I'm inexperienced, I'm more used to languages like C++ where you declare a vector of vectors).
Regarding the last question, I didn't know how to use mean() on a range of elements of an array, so I just did it myself.

Sign in to comment.

Accepted Answer

Guillaume
Guillaume on 17 Oct 2019
See my comments to the question.
Using a matrix, and assuming you're using R2019b since you haven't indicated a matlab version:
totalreps = readmatrix('totalReps.xlsx'); %read the lot as a matrix
totalreps = fillmissing(totalreps, 'constant', 0); %replace the NaNs by 0 since it makes no difference
repMeans = zeros(size(totalreps, 1), 1); %create a COLUMN vector since we're working on rows. You can make it 'single' if you wish.
for row = 1:size(totalreps, 1);
validcount = nnz(totalreps(row, :));
repMeans = mean(totalreps(row, round(validcount * 0.25) : round(validcount * 0.75)));
end

More Answers (0)

Categories

Find more on Creating and Concatenating Matrices in Help Center and File Exchange

Community Treasure Hunt

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

Start Hunting!