# Vector operation on datasets

I have a dataset like:

set1 = {{-16.7057, -10.7875, -26.8102}, {-13.2357, 25.903, 13.9369},
{22.6074,  3.4955, -30.795}, {8.31895, -15.6811, 42.3093}};
set2 = {{-16.705, -10.787, -26.81}, {-13.236, 25.903, 13.937},
{22.607,  3.495, -30.795}, {8.319, -15.681, 42.309}}


They are pretty close to each other. Now I want to take the Norm of each element of set1[[i]] and subtract it from Norm of each element of the set2[[i]]. And get the output as {a1, a2, a3, a4}. How can I do that without using any loop like For loop?

I just want to add few things for the sake of completeness if the sets are like below then what should be the action:

set1b = {{{-16.7056, -10.78745,-26.81020}, {-13.235671, 25.903009, 13.936884}, {22.6074, 3.495498, -30.79496}, {8.3189, -15.681, 42.309}}, {{1.7960000, 34.50099, -10.9480}, {-22.420000, -10.4510000, 24.980}, {1.183999,-42.707000000, -17.586999999}, {17.47500, 20.652000, 9.18399}}};

set2b = {{{-16.705, -10.787, -26.81}, {-13.236, 25.903, 13.937}, {22.607, 3.495, -30.795}, {8.319, -15.681, 42.309}}, {{1.796, 34.501, -10.948}, {-22.42, -10.451, 24.981}, {1.184, -42.707, -17.587}, {17.475, 20.652,  9.184}}};


Editted last part

• It's very annoying when people wait for an answer to then change the rules of the question. Please don't do that in the future. Read about moving the goalpost Commented Jul 19, 2018 at 19:16
• I am sorry...never do it again Commented Jul 19, 2018 at 19:19

ClearAll[normDif]
normDif = Apply[Subtract, Sqrt @ Total[{##}^2, {-1}], {0}] &;

normDif[set1, set2]


{0.000672543, -0.000166313, 0.000281282, 0.00030175}

normDif[set1b, set2b]


{{0.000606338, -0.000177899, 0.00024899, -0.0000181312},
{-9.51991*10^-6, -0.000710573, -2.60074*10^-8, -3.2146*10^-6}}

Timings:

SeedRandom[1]
{s1, s2} = RandomReal[1000, {2, 1000000, 3}];

r1 = normDif[s1, s2]; // RepeatedTiming // First


0.0887

r2 = Norm /@ s1 - Norm /@ s2; // RepeatedTiming // First


0.158

r3 = Apply[Subtract, Map[Norm] /@ {s1, s2}]; //  RepeatedTiming // First


0.155

Norm /@ {Chop[r1 - r2], Chop[r1 - r3]}


{0, 0}

Did not include Subtract @@ MapAt[Norm, {s1, s2}, {All, All}] in timing experiments because computation was aborted due to limitations of the free Wolfram Cloud plan.

• Thank you very much Commented Jul 19, 2018 at 20:29

You may use the levelspec syntax of Map with Subtract.

Norm is Maped to the second last level of the list; the vectors. Subtract is then Applyed to the items in the first level of the list.

Subtract @@ Map[Norm, {set1, set2}, {-2}]

{0.000672543,-0.000166313,0.000281282,0.00030175}

Subtract @@ Map[Norm, {set1b, set2b}, {-2}]

{{0.000606338,-0.000177899,0.00024899,-0.0000181312},
{-9.51991*10^-6,-0.000710573,-2.60074*10^-8,-3.2146*10^-6}}


Hope this helps.

Norm /@ set1 - Norm /@ set2


If there are extra brackets, then:

newset1 = set1[[1]]


and so forth.

• Thanks for the answer: I have added some edit to the question. Please have a look. Commented Jul 19, 2018 at 19:10
• Then replace: newset1 = set1[[1]] to eliminate the outer brackets. Commented Jul 19, 2018 at 19:11
• David, it is not extra brackets; set1b and set2b are 2X4X3 arrays.
– kglr
Commented Jul 19, 2018 at 21:14
Subtract @@ MapAt[
Norm
, {set1, set2}
, {All, All}
]


{0.000672543, -0.000166313, 0.000281282, 0.00030175}

Equivalently

Apply[Subtract, Map[Norm] /@ {set1, set2}]


Use Join[set1b, set2b] instead of {set1, set2} for the new case.

• Thanks for the answer: I have added some edit to the question. Please have a look. Commented Jul 19, 2018 at 19:10

If it is about speed, one can do slightly faster (at least on my machine) as follows:

SeedRandom[1]
{s1, s2} = RandomReal[1000, {2, 1000000, 3}];

r1 = normDif[s1, s2]; // RepeatedTiming // First

r4 = Subtract[
Sqrt[(s1^2).ConstantArray[1., 3]],
Sqrt[(s2^2).ConstantArray[1., 3]]
]; // RepeatedTiming // First

r1 == r4


0.0663

0.024

True

Also quite nice, drawing some more attention to the really useful function NDSolveFEMMapThreadDot that was shown to me by user21:

r5 = Subtract[
Sqrt[NDSolveFEMMapThreadDot[s1, s1]],
Sqrt[NDSolveFEMMapThreadDot[s2, s2]]
]; // RepeatedTiming // First

r1 == r5
`

0.033

True