Apply EuclideanDistance at a certain level in Mathematica
Please consider:
daList = {{{21, 18}, {20, 18}, {18, 17}, {20, 15}},
{{21, 18}, {20, 18}, {21, 14}, {21, 14}}};
I would like to compute the distance between each point in the 2 sub-lists of that list:
Yet I need to use a Function
to apply at the correct level:
Function[seqNo,
EuclideanDistance[#, {0, 0}] & /@ daList[[seqNo]]] /@
Range[Length@daList]
out = {{3 Sqrt[85], 2 Sqrt[181], Sqrt[613], 25}, {3 Sqrt[85], 2 Sqrt[181],
7 Sqrt[13], 7 Sqrt[13]}}
Is there a way to avoid this heavy function there? To specify the level avoiding my Function with seqNo as argument? :
EuclideanDistance[#, {0, 0}] & /@ 开发者_运维百科daList
out={EuclideanDistance[{{21, 18}, {20, 18}, {18, 17}, {20, 15}}, {0, 0}],
EuclideanDistance[{{21, 18}, {20, 18}, {21, 14}, {21, 14}}, {0, 0}]}
Have you tried the Level specification in Map?
Map[EuclideanDistance[#, {0, 0}] &, daList, {2}]
gives
{{3 Sqrt[85],2 Sqrt[181],Sqrt[613],25},{3 Sqrt[85],2 Sqrt[181],7 Sqrt[13],7 Sqrt[13]}}
To complement the answer of @Markus: if your daList
is very large and numerical, the following will be much faster (like 30x), although somewhat less general:
Sqrt@Total[daList^2,{3}]
Here is an example:
In[17]:= largeDaList = N@RandomInteger[30,{100000,4,2}];
In[18]:= Map[EuclideanDistance[#,{0,0}]&,largeDaList,{2}]//Short//Timing
Out[18]= {0.953,{{31.7648,34.6699,20.3961,31.305},<<99998>>,{<<18>>,<<2>>,0.}}}
In[19]:= Sqrt@Total[largeDaList^2,{3}]//Short//Timing
Out[19]= {0.031,{{31.7648,34.6699,20.3961,31.305},<<99998>>,{<<18>>,<<2>>,0.}}}
The reason is that functions like Power
and Sqrt
are Listable
, and you push the iteration into the kernel. Functions like Map
can also auto-compile the mapped function in many cases, but apparently not in this case.
EDIT
Per OP's request, here is a generalization to the case of non-trivial reference point:
refPoint = {3, 5};
Sqrt@Total[#^2, {3}] &@Transpose[Transpose[daList, {3, 2, 1}] - refPoint, {3, 2, 1}]
It is still fast, but not as concise as before. For comparison, here is the code based on Map
- ping, which only needs a trivial modification here:
Map[EuclideanDistance[#, refPoint] &, daList, {2}]
The performance difference remains of the same order of magnitude, although the vectorized solution slows down a bit due to the need for non-trivial transpositions.
精彩评论