Given that there is a set of points, for example, {{3,4,2},{5,2,-1}}
. How do I go about selecting the point that has the lowest absolute x, y or z-coordinate from the list? In this case, the point selected should be {{5,2,-1}}
as 1 is the lowest absolute value among all the points. Would the command Select[{{3,4,2}, {5,2,-1}}, ...]
be good enough to perform such operation? Specifically, my understanding is that Select[{{3,4,2}, {5,2,-1}}, ...]
is useful for selecting each individual point that satisfies certain condition stated in the command, so the question is whether it would be possible to compare 2 different points to select the desired point under the Select[...]
operation. Or would there be a better alternative to getting the desired point?
3 Answers
Since Min returns the smallest element of any of the lists, you can use Position:
list = RandomReal[1, {50, 3}];
list[[Position[list, Min[Abs@list]][[1, 1]]]]
-
1$\begingroup$ I guess you will need an extra
Abs
before theMean
. $\endgroup$ Nov 8, 2012 at 18:48 -
$\begingroup$ Ah yes, I missed the lowest absolute part $\endgroup$ Nov 8, 2012 at 18:51
-
$\begingroup$ I'd use
Pick[]
for the purpose myself... $\endgroup$ Nov 8, 2012 at 23:21
Select
only looks at each element in the list to decide if it stays or it doesn't, much like Cases
. Some options
f1 = Extract[#, (First@Position[Flatten@Abs@#, Min@Abs@#] + 2)~Quotient~3] &;
f2 = Extract[#, Ordering[#, 1, Min@Abs@#1 < Min@Abs@#2 &]] &;
f3 = First@SortBy[#, Min@Abs@# &] &;
f4 = First@Nearest[#, {0`, 0`, 0`}, DistanceFunction -> (Min@Abs[#2 - #1] &)] &;
f5 = Extract[#, Ordering[Min /@ Abs@#, 1]] &;
f6 = Extract[#, (Ordering[Abs@Flatten@#, 1] + 2)~Quotient~3] &;
So
f1[r] // AbsoluteTiming
f2[r] // AbsoluteTiming
f3[r] // AbsoluteTiming
f4[r] // AbsoluteTiming
f5[r] // AbsoluteTiming
f6[r] // AbsoluteTiming
gives
{0.1760238, {-12.1516, 56.6547, -0.000243945}}
{0.8061080, {-12.1516, 56.6547, -0.000243945}}
{0.0430082, {-12.1516, 56.6547, -0.000243945}}
{1.1661187, {-12.1516, 56.6547, -0.000243945}}
{0.0150015, {-12.1516, 56.6547, -0.000243945}}
{0.0060008, {-12.1516, 56.6547, -0.000243945}}
-
$\begingroup$ Interesting comparisons. For your last one,
f6
, I got an additional speed boost by omitting the unused coordinates from the argument ofOrdering
:f7=Extract[#1,Ordering[Abs[#1[[All,1]]],1]]&
. $\endgroup$– JensNov 9, 2012 at 6:04 -
$\begingroup$ @Jens, I understood he wanted the minimum abs of any of the three coordinates, your suggested code would only look at the first one, right? $\endgroup$– RojoNov 9, 2012 at 13:22
-
$\begingroup$ Oh, right. I'm solving a different problem - If I do my approach for each component separately, I think your f6 wins the speed comparison again. $\endgroup$– JensNov 9, 2012 at 16:11
There's a little function I call MinBy
I like to use from time to time (see here). It relates to Min
the same way SortBy
relates to Sort
.
MinBy[list_, fun_] := list[[First@Ordering[fun /@ list, 1]]]
This function gives yet another simple solution to your question:
points = {{3, 4, 2}, {5, 2, -1}}
MinBy[points, Composition[Min, Abs]]
Note that an inherent problem with using MinBy
is that is always returns only a single result, even if there are several equivalent elements of the list that could be considered minimal. This solution will always return only a single point.