How to locate an entire column based on one value?

8 views (last 30 days)
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
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')
tmed = 0.5053
[r,c] = find(ismembertol(t, tmed, 1E-4));
row_col = [r c]
row_col = 2x2
111 3 320 19
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
idx = sub2ind(size(t), r, c)
idx = 2x1
951 7880
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
t(idx)
ans = 2x1
0.5053 0.5052
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
.
EDIT — Corrected typographical errors.
  5 Comments
Star Strider
Star Strider 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)
A = 10x10
-0.1840 1.0885 -2.0206 -1.1134 -0.8050 -1.0294 0.2714 1.1347 -0.0150 -0.4304 -0.4164 -0.2513 -0.9963 0.0027 -1.9010 -0.2864 -0.8389 -1.1578 -0.4903 -0.4042 0.0074 -0.7934 0.1429 -0.9668 -1.1607 -0.9066 0.3446 -1.1123 0.2136 1.1778 -0.3832 2.2025 -1.4934 0.3030 -0.3217 -0.1841 -0.3007 -1.4484 -0.3797 0.7890 0.0230 1.9308 -0.9886 0.4529 0.5115 0.8189 0.2398 0.5702 1.3789 -0.3604 0.4196 -0.6768 0.7539 -1.2780 -0.2931 0.4088 -1.7036 -0.3930 -2.7188 -0.7861 -0.0164 -0.2707 -1.3897 -0.6175 -0.7291 0.5047 1.1061 1.8219 1.0016 0.5403 -0.7049 0.1320 -1.3270 -0.4939 0.6516 0.1642 -1.3163 -1.7062 -0.0860 -1.2845 0.4395 1.5823 0.1089 -0.9712 0.1382 -0.4037 1.0458 0.3306 -3.4837 0.0383 -0.4066 1.8031 0.5805 -0.1327 -1.8988 0.7264 1.1519 0.0072 -1.3220 0.2506
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
ColMed = median(A)
ColMed = 1x10
-0.1002 0.6102 -0.9924 -0.5557 -0.5254 -0.0100 0.2556 -0.1929 -0.2328 -0.1610
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
Check1 = median(A,'all') == median(ColMed) % Is The Matrix Median Equal To The Medain Of The Column Medians?
Check1 = logical
0
Look = [median(A,'all') median(ColMed)] % Show Their Individual Values
Look = 1x2
-0.2177 -0.1770
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
Check2 = ColMed == median(ColMed) % Is The Median Of The Column Medians Equal To Any Of Them?
Check2 = 1x10 logical array
0 0 0 0 0 0 0 0 0 0
[r,c] = find(ismembertol(A, Look(1), 1E-2));
row_col = [r c]
row_col = 3x2
1 1 2 2 4 6
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
idx = sub2ind(size(A), r, c)
idx = 3x1
1 12 54
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
A(idx)
ans = 3x1
-0.1840 -0.2513 -0.1841
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
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.)
.
Walter Roberson
Walter Roberson on 3 Sep 2024
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
Elapsed time is 0.009425 seconds.
A
A = 25x9
0.2929 0.0002 0.6991 0.6386 0.9287 0.4889 0.4289 0.5787 0.8547 0.3655 0.1354 0.6275 0.6950 0.6883 0.8430 0.3727 0.2921 0.6618 0.3457 0.0778 0.2939 0.4399 0.9086 0.4457 0.5634 0.0411 0.9461 0.4961 0.5700 0.9381 0.4805 0.9934 0.0828 0.7613 0.9223 0.0802 0.7434 0.8918 0.5773 0.0723 0.2984 0.9813 0.1776 0.1028 0.5910 0.8836 0.6333 0.4246 0.3437 0.6069 0.6538 0.7859 0.5676 0.6423 0.0592 0.1362 0.6600 0.2060 0.0555 0.3239 0.7298 0.0782 0.3453 0.7516 0.6257 0.8540 0.9461 0.9035 0.2747 0.4924 0.0449 0.1229 0.4251 0.2896 0.8255 0.2323 0.1255 0.6340 0.8271 0.0264 0.2677 0.7647 0.2324 0.6675 0.0428 0.2056 0.0075 0.4890 0.6607 0.5377
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
Medians
Medians = 1x9
0.4251 0.3908 0.4670 0.4922 0.6719 0.4889 0.5199 0.5676 0.3242
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
Per_row_position
Per_row_position = 1x9
9 25 21 18 22 1 18 6 11
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
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))
Per_row_position2 = 1x9
9 25 21 18 22 1 18 6 11
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
toc
Elapsed time is 0.015615 seconds.
... except that it takes more memory, and is a bit faster.

Sign in to comment.

Products


Release

R2023b

Community Treasure Hunt

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

Start Hunting!