How to locate an entire column based on one value?
Show older comments
I have a 25x420 matrix. I want to locate the median number within the matrix. Once the median is located, I want to call the column that it came out of. If i do "median(t)" it gives the median of each column but from there I can call the total median value and its column of values.
columns = 25;
rows = 420;
t = rand(rows,columns);
Answers (1)
Star Strider
on 30 Aug 2024
Edited: Star Strider
on 30 Aug 2024
The way the median is calculated may not exactly match any of the values in the matrix.
The solutiion to that problem is to use the ismembertol function to find the element or elements that are the closest match to it. That returns a logical array, and using find with that result will return the rows and columns of the closest matches that ismembertol returns.
Try something like this —
columns = 25;
rows = 420;
t = rand(rows,columns);
tmed = median(t, 'all')
[r,c] = find(ismembertol(t, tmed, 1E-4));
row_col = [r c]
idx = sub2ind(size(t), r, c)
t(idx)
.
EDIT — Corrected typographical errors.
5 Comments
Wow, I didn't expect that the median would not necessarily be one of the values.
% Create sample data.
data = rand(1000, 1000);
% Have it compute the median.
m = median(data, "all")
% See if it's actually in the data, like we'd expect.
[rows, cols] = find(data == m)
Walter Roberson
on 31 Aug 2024
When there are an even number of input values, then the median is the mean of the two central values. If there are duplicate values, then potentially the two central values will happen to be identical and so the median would be the same as the central values... but in that case, you would have to expect that the source column would match multiple columns. If there are no duplicates, then with an even number of values the median will not exactly match any of the input values.
It is not completely clear whether the position of the median is desired per row or for the overall matrix.
Either way, with there being an even number of entries per row and for the overall matrix, the position of the median would have to be either empty or else a list of at least two values.
Kendell
on 3 Sep 2024
My pleasure!
I limited this to a small matrix for ease of interpretation and readability. Everything here would also apply to your (25x420) matrix.
Just using median will return the column medians of a matrix —
A = randn(10)
ColMed = median(A)
Check1 = median(A,'all') == median(ColMed) % Is The Matrix Median Equal To The Medain Of The Column Medians?
Look = [median(A,'all') median(ColMed)] % Show Their Individual Values
Check2 = ColMed == median(ColMed) % Is The Median Of The Column Medians Equal To Any Of Them?
[r,c] = find(ismembertol(A, Look(1), 1E-2));
row_col = [r c]
idx = sub2ind(size(A), r, c)
A(idx)
However, the median of the entire array may not equal the median of the column medians, and the median of the column medians may not be equal to any of them.
Your matrix has an even number of elements (10500), so it is not likely that any one of them will equal the median of the matrix.
It may not be possible to do what you describe wanting to do. (I am not even certain what that is.)
.
Since the input is 25 x 420 and the desired output is 1 x 420 then the per-column median is desired. That is an odd number of entries in the columns, so (provided that there are no nan values) the per-column median will be exactly the same as (at least one of) the rows.
A = rand(25,9);
Medians = median(A);
tic
Per_row_position = sum(cumprod(Medians ~= A)) + 1;
toc
A
Medians
Per_row_position
The sum(cumprod) is a trick to locate the positions of matching entries in a parallel manner. It is effectively a
tic
Per_row_position2 = arrayfun(@(IDX) find(A(:,IDX)==Medians(IDX),1), 1:size(A,2))
toc
... except that it takes more memory, and is a bit faster.
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!