# Add, subtract, multiply, divide etc, lists that are coordinate pairs e.g. time histories

I often do signal processing and have lists that may be time series or spectra that are in the form of

$$\{ \{x1,y1\},\{x2,y2\}, \{x3,y3\}...\}$$

I usually have lists with all the same x values and want to do operations like adding, subtracting, multiplying etc, corresponding y values. The "proper" way of doing this is to strip of the x values and then operate on the y values and afterwards put the x values back. However, this is tedious and I have developed the following short cut to avoid stripping off the x values.

Here are some example lists and a plot of what they look like:

a = Table[{x, BesselJ[0, x]}, {x, 0, 30, 0.2}];
b = Table[{x,
E^(-0.2 (x - 0.017 x^2)) Cos[0.14 2 π ( x + 0.004 x^2)]},
{x, 0, 30, 0.2}];
ListLinePlot[{a, b}]


The code I use to do simple operations, and an example, is

 ClearAll[arith];
arith[exp_, a_] := Transpose[{a[[All, 1]], exp[[All, 2]]}]

ListLinePlot[{a, b, arith[a - b, a]}]


In the code arith I let the x values be wrecked while working on the y values and then replace the x values in the final output using the second parameter. This works well and can get satisfactorily complicated which is most useful:

ListLinePlot[{a, b, arith[5 (a - b)/(a + b + 10), a]}]

ListLinePlot[{a, b,
arith[
z = a + b + 2 + 3 I;
z Conjugate[z] - 15,
a]}]


However, it will not work if the x and y values get mixed or if a number is added that has an inappropriate x value. For example a common operation is

arith[a - Mean[a], a]


This does not work because Mean correctly takes the mean of the x and y values and now there is a list with wrong abscissae. To help me cope with this case I changed arith to

ClearAll[arith];
SetAttributes[arith, HoldAll];
arith[exp_, a_] := Module[{e1, e},
e1 = Hold[exp] /. {
Mean[e_] :> Mean[e[[All, 2]]],
StandardDeviation[e_] :> StandardDeviation[e[[All, 2]]]
}
;
Transpose[{a[[All, 1]], ReleaseHold[e1][[All, 2]]}]
]


The HoldAll gives me a chance to work on Mean and StandardDeviation. Thus I can now do:

 ListLinePlot[{a,
arith[a - Mean[a], a],
arith[(a - Mean[a])/StandardDeviation[a], a]}]


However, I am now thinking that this is not the way to go but I should strip off all the x values and then do the operations. I tried to identify lists in the Held expression but failed. Can anyone suggest a way forward? Thanks

• Just to check: a and b are always guaranteed to have the same set of abscissas, but not necessarily in the same order? May 13, 2020 at 11:02
• @J.M. Yes, a and b and sometimes c, d and more all have the same abscissas. I don't catch the not in the same order point. The abscissas are in the same order for each list. It would be an extension to have different orders, although come to think of it I sometimes Reverse time histories and then combine them.
– Hugh
May 13, 2020 at 11:15
• By "not in the same order", I meant that you might consider sets like a = {{x1, y1}, {x2, y2}, {x3, y3}} and b = {{x1, f1}, {x3, f2}, {x2, f3}}. I guess you don't need to worry about those? (Otherwise, that would complicate possibly straightforward approaches.) May 13, 2020 at 11:28
• Anyway: a hacky way would be to temporarily convert your point list to an association, so that you can operate accordingly, e.g. KeyValueMap[List, Association[Rule @@@ a] + Association[Rule @@@ b]] and With[{at = Association[Rule @@@ a]}, KeyValueMap[List, at - Mean[at]]]. I do find the concept of inexact numbers as keys a little iffy, tho. May 13, 2020 at 11:34
• What's wrong with doing arithmetic with TimeSeries object itself? May 13, 2020 at 11:54