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

Mathematica graphics

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

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

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

Mathematica graphics

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,
   z = a + b + 2 + 3 I;
   z Conjugate[z] - 15,

enter image description here

enter image description here

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

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:

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

enter image description here

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

  • $\begingroup$ Just to check: a and b are always guaranteed to have the same set of abscissas, but not necessarily in the same order? $\endgroup$ May 13, 2020 at 11:02
  • $\begingroup$ @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. $\endgroup$
    – Hugh
    May 13, 2020 at 11:15
  • $\begingroup$ 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.) $\endgroup$ May 13, 2020 at 11:28
  • 1
    $\begingroup$ 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. $\endgroup$ May 13, 2020 at 11:34
  • 1
    $\begingroup$ What's wrong with doing arithmetic with TimeSeries object itself? $\endgroup$
    – swish
    May 13, 2020 at 11:54


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.