Averaging every nth element ignoring zeros into a matrix
2 views (last 30 days)
Show older comments
Dear all,
I am trying to analyse a dataset and struggling with a probably quite simple question and so far the research in the forum hasn't helped me much. I have a m*n matrix and want to "bin" (I know its the wrong word for it, but for lack of a better word..) it into a 10x10 matrix, thereby calculating the average of the values in each "bin". I have coordinates for cells with a specific activation value, which I have transformed into a matrix with the coordinates as row/column specs and the value as the cell-value. Now I want to create a heat map to visualize if there are specific areas with a higher activity than others. Since there are not always cells at all coordinates, the 0 in the matrix are not to be used for further calculations.
I have successfully used a very neat approach that a user posted in this forum a long time ago for summing up the values into a bin, which was perfect for my previous analysis, but now I need to average instead of summing. The code I have previously used ( Source ) would look like this:
IND = [0 0 0 0 0 0; 0 10 15 0 0 0; 0 0 0 0 0 7; 0 0 0 0 0 8];
[n,m] = size(IND);
ind = (1:n)';
IND2 = sparse(ceil(ind/2),ind,1)*IND;
ind = (1:m)';
IND3 = IND2*sparse(ind,ceil(ind/3),1);
Summing in 2 directions to end up with a matrix that is 2x2. Is there an easy way that I am missing to transform this code into averaging instead of summing? (I stumbled upon reshaping methods but couldn't quite get them to work to sum up in both directions) For the few attempts where I could average in one of the desired directions, I realized that it would calculate the average with all elements, including the zeros. Is there a way of excluding these in the calculation but maintain the order of the matrix? (if I use mean(IND(IND~=0)), it will give me the result as the first cell instead of the "bin" where the data is from). I would be very happy for help in any kind of way, thanks so much!
0 Comments
Answers (2)
Walter Roberson
on 26 Sep 2016
Edited: Walter Roberson
on 26 Sep 2016
See accumarray(), which allows you to specify a custom function. You can specify @mean . For example,
index = randi(50, 20, 1);
data = rand(20, 1);
accumarray(index, data, [], @mean)
2 Comments
Walter Roberson
on 27 Sep 2016
Transform your non-integer variables into integer values.
range_min = 0; range_max = 1;
number_of_bins = 10;
x = rand(1, 20) * (range_max - range_min) + range_min;
x_as_index = floor( double(x(:) - range_min)./(range_max - range_min)./(1+eps) * number_of_bins ) + 1;
y = rand(20, 1);
counts = accumarray(index, data, [], @nanmean);
The 1+eps divisor is to account for the possibility that some data is exactly equal to the upper end of the range, but you might want to get rid of it there depending on how you think about the values that are exactly on the bin boundaries. For example if you have values in the range 0 to 1 and you have 2 bins, then it is easy to say "Oh yes, make 1/2 the dividing point between the bins", but do you make the rule 0 < x <= 1/2 and 1/2 < x <= 1, or do you make the rule 0 <= x < 1/2, 1/2 <= x < 1, or do you make the rule 0 <= x < 1/2, 1/2 <= x <= 1 ? In the first of those, the value 1 exactly gets left out of the rule; in the second of those, the value 0 exactly gets left out of the rule; in the third of those, the second bin is larger than the first by one value. In binary floating point spaced equally apart at 1/2^53, then 0 <= x <= 1 involves an odd number of values so there is no one "right" answer.
See Also
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!