I have a matrix and want to extract rows according to some criterion. Then I have other matrices and want to extract the same rows. For example, if my criterion is to find rows where all the elements are smaller than some number, I can write
m = Table[i j/10., {i, 5}, {j, 3}]
which returns
{
{0.1, 0.2, 0.3},
{0.2, 0.4, 0.6},
{0.3, 0.6, 0.9},
{0.4, 0.8, 1.2},
{0.5, 1., 1.5}
}
Then
Select[m, Max[#] < 1. &]
selects the first three rows of m
. Alternatively,
m[[{1, 2, 3}, All]]
also extracts the same first three rows. So if I had the list {1,2,3}
, I could use that list to extract the corresponding rows from any number of other objects. To find the list, I tried
Position[m, Max[#] < 1. &]
but it returns the empty list. Why doesn't this work? Is there a better approach? Also, for my real application, execution speed is potentially important.
Update: I am impressed at how many different ways to do this exist! I was also interested in how fast the approaches run. I ran a test on a slightly different task (closer to my application, although my initial list isn't random!).
m = RandomReal[{-1, 1}, {1000, 20}];
lst1 = Position[(Max[Abs[#]] < 0.9) & /@ m, True] // Flatten //
AbsoluteTiming;
lst2 = ResourceFunction["SelectIndices"][m, (Max[Abs[#]] < 0.9) &] //
Flatten // AbsoluteTiming;
lst3 = Flatten@
Position[
Flatten[ResourceFunction[
"ThroughOperator"][{(Max[Abs[#]] < 0.9) &}] /@ m], True] //
AbsoluteTiming;
lst4 = ResourceFunction["SelectPositions"][m, (Max[Abs[#]] < 0.9) &] //
Flatten // AbsoluteTiming;
lst5 =
Position[m, _?(AllTrue[(Max[Abs[#]] < 0.9) &]), {1},
Heads -> False] // AbsoluteTiming;
lst6 = Flatten[
Table[Position[m, Select[AllTrue[# < 1 &]][m][[i]]], {i, 1,
Length@Select[AllTrue[(Max[Abs[#]] < 0.9) &]][m]}]] //
AbsoluteTiming;
{lst1[[1]], lst2[[1]], lst3[[1]], lst4[[1]], lst5[[1]], lst6[[1]]}
returns
{0.002089, 0.002717, 0.003723, 0.007242, 0.009424, 1.09962}
Sorry for obsessing, but here's a new winner (replaces anon. function with explicit one):
(Position[LessThan[0.9] /@ (Max /@ Abs[m]), True] // Flatten //
AbsoluteTiming)[[1]]
returns 0.001294. By the way, if the number of rows is smaller than 1000, the ordering of which is fastest changes. (Try 100 and 10.) But method 1 and this variant seem always to be the fastest.
ResourceFunction["SelectPositions"]
orResourceFunction["SelectIndices"]
to get the locations of interest, then use those inPart
orExtract
. $\endgroup$