4
$\begingroup$

We have two matrices list1 and list2 with identical first columns and a code written for subtracting the second columns. We should make a third matrix with the same first column and the second column equal to the difference between second columns of the original matrices. The code:

dif = ConstantArray[0, {Length@list1, 2}]
Do[

   j = list1[[;; , 1]][[i]];
   dif[[i, 2]] = list1[[;; , 2]][[i]] - list2[[;; , 2]][[i]];
   dif[[i, 1]] = j;

  , {i, 1, Length@list1}];

How can we use # to shorten the above code in an efficient way?

list1={{0.5,1.2},{0.75,1.6},{1.1,4.3},{1.3,1.7},{2.0,3.2}};
list2={{0.5,1.0},{0.75,1.9},{1.1,2.2},{1.3,0.7},{2.0,2.1}};
$\endgroup$
1
  • 2
    $\begingroup$ Related: (3069) $\endgroup$
    – Mr.Wizard
    Commented Jun 4, 2017 at 23:55

10 Answers 10

9
$\begingroup$

Based on an elegant method given by Mr Wizard (and originally posted as a comment):

list1 - list2.{{0, 0}, {0, 1}}

{0.5, 0.2}, {0.75, -0.3}, {1.1, 2.1}, {1.3, 1.}, {2., 1.1}}

Edit

This may be generalized somewhat:

list1 - list2.DiagonalMatrix[{0, 1}]

For

list3 = {{0.1, 10, 100, 1000}, {0.2, 20, 200, 2000}, {0.3, 30, 300, 
3000}, {0.4, 40, 400, 4000}, {0.5, 50, 500, 5000}};

list4 = {{0.1, 5, 50, 500}, {0.2, 10, 100, 1000}, {0.3, 15, 150, 
1500}, {0.4, 20, 200, 2000}, {0.5, 25, 250, 2500}};

Subtract all columns (of list4) except column 1:

list3 - list4.DiagonalMatrix[{0, 1, 1, 1}]

$$\left( \begin{array}{cccc} 0.1 & 5. & 50. & 500. \\ 0.2 & 10. & 100. & 1000. \\ 0.3 & 15. & 150. & 1500. \\ 0.4 & 20. & 200. & 2000. \\ 0.5 & 25. & 250. & 2500. \\ \end{array} \right)$$

Subtract columns 2 & 3, and subtract twice column 4:

list3 - list4.DiagonalMatrix[{0, 1, 1, 2}] // MatrixForm

$$\left( \begin{array}{cccc} 0.1 & 5. & 50. & 0. \\ 0.2 & 10. & 100. & 0. \\ 0.3 & 15. & 150. & 0. \\ 0.4 & 20. & 200. & 0. \\ 0.5 & 25. & 250. & 0. \\ \end{array} \right)$$

Edit 2

After this answer by Carl Woll:

Subtract all columns (of list4) except the first:

list3 - (list4 // #.SparseArray[{Band[{2, 2}] -> 1}, 
   Dimensions[#][[2]]] &) // MatrixForm

$$\left( \begin{array}{cccc} 0.1 & 5. & 50. & 500. \\ 0.2 & 10. & 100. & 1000. \\ 0.3 & 15. & 150. & 1500. \\ 0.4 & 20. & 200. & 2000. \\ 0.5 & 25. & 250. & 2500. \\ \end{array} \right)$$

Edit 3 Removed extraneous material to here

$\endgroup$
1
  • $\begingroup$ And, of course, as Dot may be considered a special case of Inner, list1 - Inner[Times, list2, {{0, 0}, {0, 1}}] $\endgroup$
    – user1066
    Commented May 30, 2017 at 11:48
5
$\begingroup$

Here is a timing comparison of the solutions proposed so far.

Initial setup:

n = 10^6;
list1 = RandomReal[1, {n, 2}];
list2 = list1;
list2[[All, 2]] = RandomReal[1, n];

Timings (obtained with Mathematica 8.0.4 on Windows 7 x64):

In[2]:= $Line = 0;
m1 = list1 - list2.{{0, 0}, {0, 1}}; // AbsoluteTiming // First
m2 = # {2, 1} & /@ list1 - list2; // AbsoluteTiming // First
m3 = list1 - ({0, 1} # & /@ list2); // AbsoluteTiming // First
m4 = Thread[{list1[[All, 1]], list1[[All, 2]] - list2[[All, 2]]}]; //  AbsoluteTiming // First
m5 = Thread[{#1 & @@@ list1, (#2 & @@@ list1) - (#2 & @@@ list2)}]; // AbsoluteTiming // First
m6 = MapThread[{First[#1], Last[#1] - Last[#2]} &, {list1, list2}]; // AbsoluteTiming // First
m7 = Transpose@{list1[[;; , 1]], list1[[;; , 2]] - list2[[;; , 2]]}; // AbsoluteTiming // First
☺ = {# & @@ #, # - #2 & @@ (#2 & @@@ {##})} & @@@ ({##}\[Transpose]) &; m8 = ☺[list1, list2]; // AbsoluteTiming // First
m9 = With[{cs1 = Complex @@@ list1, 
      cs2 = Composition[Conjugate, Complex] @@@ list2},
     Transpose@{Re[cs1], Im[cs1 + cs2]}]; // AbsoluteTiming // First
m1 == m2 == m3 == m4 == m5 == m6 == m7 == m8 == m9

Out[1]= 0.0930053
Out[2]= 0.3020172
Out[3]= 0.3110178
Out[4]= 0.4440253
Out[5]= 3.3061891
Out[6]= 4.9412827
Out[7]= 0.1540088
Out[8]= 11.7486720
Out[9]= 3.6802105
Out[10]= True

The absolute winner is elegant solution proposed by tomd in the comments:

list1 - list2.{{0, 0}, {0, 1}}

The second place belongs to the second solution by Anjan Kumar:

Transpose@{list1[[;; , 1]], list1[[;; , 2]] - list2[[;; , 2]]}
$\endgroup$
4
$\begingroup$

Using MapThread

MapThread[{First[#1], Last[#1] - Last[#2]} &, {list1, list2}]

{{0.5, 0.2}, {0.75, -0.3}, {1.1, 2.1}, {1.3, 1.}, {2., 1.1}}

Using Transpose

Transpose@{list1[[;; , 1]], list1[[;; , 2]] - list2[[;; , 2]]}
$\endgroup$
4
$\begingroup$
list1 - ({0, 1} # & /@ list2)

{{0.5, 0.2}, {0.75, -0.3}, {1.1, 2.1}, {1.3, 1.}, {2., 1.1}}

Also:

☺ = {# & @@ #, # - #2 & @@ (#2 & @@@ {##})} & @@@ ({##}) &;

Mathematica graphics

☺[list1, list2]

{{0.5, 0.2}, {0.75, -0.3}, {1.1, 2.1}, {1.3, 1.}, {2., 1.1}}

$\endgroup$
3
$\begingroup$
Thread[{list1[[All, 1]], list1[[All, 2]] - list2[[All, 2]]}]
(* {{0.5, 0.2}, {0.75, -0.3}, {1.1, 2.1}, {1.3, 1.}, {2., 1.1}} *)


Thread[{#1 & @@@ list1, (#2 & @@@ list1) - (#2 & @@@ list2)}]
(* {{0.5, 0.2}, {0.75, -0.3}, {1.1, 2.1}, {1.3, 1.}, {2., 1.1}} *)
$\endgroup$
3
$\begingroup$

In:

list1 = {{0.5, 1.2}, {0.75, 1.6}, {1.1, 4.3}, {1.3, 1.7}, {2.0, 3.2}};
list2 = {{0.5, 1.0}, {0.75, 1.9}, {1.1, 2.2}, {1.3, 0.7}, {2.0, 2.1}};

(*Method 1*)
cs1 = Complex @@@ list1 ;
cs2 = Conjugate @*Complex @@@ list2;
Transpose@{Re[cs1], Im[cs1 + cs2]}

(*Method 2*)
 # {2, 1} & /@ list1 - list2

Out:

{{0.5, 0.2}, {0.75, -0.3}, {1.1, 2.1}, {1.3, 1.}, {2., 1.1}}
{{0.5, 0.2}, {0.75, -0.3}, {1.1, 2.1}, {1.3, 1.}, {2., 1.1}}
$\endgroup$
2
$\begingroup$
a = {{0.5, 1.2}, {0.75, 1.6}, {1.1, 4.3}, {1.3, 1.7}, {2.0, 3.2}};
b = {{0.5, 1.0}, {0.75, 1.9}, {1.1, 2.2}, {1.3, 0.7}, {2.0, 2.1}};

KeyValueMap[List] @ Merge[Apply @ Subtract] @ MapApply[Rule] @ Join[a, b]

{{0.5, 0.2}, {0.75, -0.3}, {1.1, 2.1}, {1.3, 1.}, {2., 1.1}}

This also functions if the two lists are unsorted:

b = RotateRight[b];

KeyValueMap[List] @ Merge[Apply @ Subtract] @ MapApply[Rule] @ Join[a, b]

{{0.5, 0.2}, {0.75, -0.3}, {1.1, 2.1}, {1.3, 1.}, {2., 1.1}}

$\endgroup$
1
$\begingroup$
a = {{0.5, 1.2}, {0.75, 1.6}, {1.1, 4.3}, {1.3, 1.7}, {2.0, 3.2}};

b = {{0.5, 1.0}, {0.75, 1.9}, {1.1, 2.2}, {1.3, 0.7}, {2.0, 2.1}};

Using PrependColumn by Michael Sollami

FirstColumn = ResourceFunction["PrependColumn"];

FirstColumn[List @* Last /@ (a - b), First /@ a]

{{0.5, 0.2}, {0.75, -0.3}, {1.1, 2.1}, {1.3, 1.}, {2., 1.1}}

$\endgroup$
1
$\begingroup$

Using Transpose and MapAt:

m1 = {{0.5, 1.2}, {0.75, 1.6}, {1.1, 4.3}, {1.3, 1.7}, {2.0, 3.2}};
m2 = {{0.5, 1.0}, {0.75, 1.9}, {1.1, 2.2}, {1.3, 0.7}, {2.0, 2.1}};
b = {m1, m2};

Thread[#[[1]] & /@ MapAt[{#[[1]] - #[[2]]} &, Thread[Thread /@ b], {2}]]

(*{{0.5, 0.2}, {0.75, -0.3}, {1.1, 2.1}, {1.3, 1.}, {2., 1.1}}*)
$\endgroup$
0
$\begingroup$
m1 = {{0.5, 1.2}, {0.75, 1.6}, {1.1, 4.3}, {1.3, 1.7}, {2.0, 3.2}};

m2 = {{0.5, 1.0}, {0.75, 1.9}, {1.1, 2.2}, {1.3, 0.7}, {2.0, 2.1}};

Using ReplaceAll:

Thread[{Reverse /@ m1, m1 - m2}] /. x : {_, _} :> x[[All, 2]]

{{0.5, 0.2}, {0.75, -0.3}, {1.1, 2.1}, {1.3, 1.}, {2., 1.1}}

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.