# Subtracting second columns of two matrices

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}};

• Related: (3069) Commented Jun 4, 2017 at 23:55

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

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

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]]}


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]]}

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 & @@@ {##})} & @@@ ({##}) &;


☺[list1, list2]


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

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}} *)


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}}

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}}

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}}

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};

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

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}}