4
$\begingroup$

I imported 2 lists of the form {{x1,y1}, {x2,y2}, ...} and {{x1,y'1}, {x2,y'2}, ...} into Mathematica. I want to make a ListPlot the list {{x1, y1 - y'1}, {x2, y2 - y'2}, ...}.

How can I create the third list by subtracting only the second column values of the first two lists keeping the first column intact.

$\endgroup$
3
  • $\begingroup$ Something like MapThread[(({Mean[#1], Subtract @@ #2} &) @@ Transpose[##]) &, {list1, list2}], I guess. (I'm not at a computer to check.) $\endgroup$ Commented Sep 17, 2017 at 18:56
  • $\begingroup$ p={{x1,y1},{x2,y2}}; q={{x1,Y1},{x2,Y2}};f[r_,s_]:={r[[1]],r[[2]]-s[[2]]}; MapThread[f,{p,q}] $\endgroup$
    – Bill
    Commented Sep 17, 2017 at 19:11
  • $\begingroup$ look up Part $\endgroup$
    – user42582
    Commented Sep 17, 2017 at 19:16

6 Answers 6

4
$\begingroup$

Another solution is:

p = {{x1, y1}, {x2, y2}}; q = {{x1, Y1}, {x2, Y2}};
p - ({0, 1} # & /@ q)
(* {{x1, y1 - Y1}, {x2, y2 - Y2}} *)

This works by simply replacing the first column of one of the lists with 0 before subtracting.

$\endgroup$
0
3
$\begingroup$

One possibility is to use Association. Here is a small example:

SeedRandom[1]
d1 = Thread[{Range[10], RandomReal[1, 10]}]
d2 = Thread[{Range[10], RandomReal[1, 10]}]

{{1, 0.817389}, {2, 0.11142}, {3, 0.789526}, {4, 0.187803}, {5, 0.241361}, {6, 0.0657388}, {7, 0.542247}, {8, 0.231155}, {9, 0.396006}, {10, 0.700474}}

{{1, 0.211826}, {2, 0.748657}, {3, 0.422851}, {4, 0.247495}, {5, 0.977172}, {6, 0.825163}, {7, 0.925275}, {8, 0.578056}, {9, 0.29287}, {10, 0.208051}}

Convert to an Association object:

a1 = AssociationThread @@ Transpose @ d1
a2 = AssociationThread @@ Transpose @ d2

<|1 -> 0.817389, 2 -> 0.11142, 3 -> 0.789526, 4 -> 0.187803, 5 -> 0.241361, 6 -> 0.0657388, 7 -> 0.542247, 8 -> 0.231155, 9 -> 0.396006, 10 -> 0.700474|>

<|1 -> 0.211826, 2 -> 0.748657, 3 -> 0.422851, 4 -> 0.247495, 5 -> 0.977172, 6 -> 0.825163, 7 -> 0.925275, 8 -> 0.578056, 9 -> 0.29287, 10 -> 0.208051|>

Now, when we subtract 2 Association objects, we get a new Association object where the values are the differences between the values of each individual Association. So:

r = a1 - a2

<|1 -> 0.605564, 2 -> -0.637237, 3 -> 0.366675, 4 -> -0.0596916, 5 -> -0.735811, 6 -> -0.759424, 7 -> -0.383029, 8 -> -0.346902, 9 -> 0.103136, 10 -> 0.492423|>

Plotting an Association is simple:

ListPlot[r]

enter image description here

$\endgroup$
1
  • $\begingroup$ Just a little warning/note: While in general I really like associations, I do sometimes find it difficult to work with them efficiently when I need access to both key and value. You can of course use MapIndexed, but then you have to take care of the List and Key wrappers... $\endgroup$
    – Lukas Lang
    Commented Sep 17, 2017 at 22:52
3
$\begingroup$

Lists in Mathematica can be picked apart with Part.

If you evaluate Dimensions[list1] the output should be something like {n,2} where n is an integer equal to the number of pairs in your list (check this on the levels of expressions in Mathematica).

Alternatively, you can think list1 as a matrix (see "Structural Operations" section) with n rows and 2 columns. The same stands true for list2.

In order to "...keep the first column" from either list you can use Part;

x = Part[list1, All, 1]

After evaluating the previous line, x now is a List with the x-coordinates of list1.

In order to "...subtract the second columns", you'll first need to obtain them as lists (also, see this for in-place manipulation).

Using again Part in a similar fashion as before will yield y1 and y2 ie the y-coordinates of lists 1 and 2. The difference this time is that we need to take the second entry from every row (that's what All stands for).

After having obtained the y1 and y2 subtracting one from the other and combining them into an output list is straightforward:

Transpose[{x,y1-y2}]
$\endgroup$
2
  • 2
    $\begingroup$ Or all on one line: Thread@{list1[[All, 1]], list1[[All, 2]] - list2[[All, 2]]} $\endgroup$
    – wxffles
    Commented Sep 17, 2017 at 21:46
  • 1
    $\begingroup$ Or Transpose[{list1[[;; , 1]], list1[[;; , 2]] - list2[[;; , 2]]}] $\endgroup$ Commented Sep 17, 2017 at 22:45
2
$\begingroup$

A straightforward approach is to use Table to perform the operation element by element. To show how this would work, I will first make some data.

With[{n = 5},
  xs = Range[n];
  y1s = y1[#] & /@ xs;
  data1 = Transpose[{xs, y1s}];
  y2s = y2[#] & /@ xs;
  data2 = Transpose[{xs, y2s}]];

This produces two list like so.

data1

{{1, y1[1]}, {2, y1[2]}, {3, y1[3]}, {4, y1[4]}, {5, y1[5]}}

data2

{{1, y2[1]}, {2, y2[2]}, {3, y2[3]}, {4, y2[4]}, {5, y2[5]}}

Now the 1st element in each pair in either of the lists can be obtained with Firsf and the 2nd element with Last, so the general term for the result list is

{First[data1[[i]]], Last[data1[[i]]] - Last[data2[[i]]]}

Therefore,

Table[{First[data1[[i]]], Last[data1[[i]]] - Last[data2[[i]]]}, {i, Length[data1]}]

will do the job, giving

{{1, y1[1] - y2[1]}, {2, y1[2] - y2[2]}, {3, y1[3] - y2[3]}, {4, y1[4] - y2[4]}, 
 {5, y1[5] - y2[5]}}

A slightly more sophisticated approach with pure functions and MapThread is given by

MapThread[{#1[[1]], #1[[2]] - #2[[2]]} &, {data1, data2}]
$\endgroup$
2
$\begingroup$
 list1 - list2.{{0, 0}, {0, 1}}

 

lst1 = Array[{x[#], y[#]} &, {5}];
lst2 = Array[{x[#], yy[#]} &, {5}];
lst1 - lst2.{{0, 0}, {0, 1}}

{{x[1], y[1] - yy[1]}, {x[2], y[2] - yy[2]}, {x[3], y[3] - yy[3]}, {x[4], y[4] - yy[4]}, {x[5], y[5] - yy[5]}}

$\endgroup$
1
$\begingroup$
lis1 = {{x1, y1}, {x2, y2}, {x3, y3}};
lis2 = {{x1, y1'}, {x2, y2'}, {x3, y3'}};
lis3 = lis1 - lis2;
Transpose[{lis1[[All, 1]], lis3[[All, 2]]}]

{{x1, y1 - y1'}, {x2, y2 - y2'}, {x3, y3 - y3'}}

$\endgroup$

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