7

I want to add several fluorescence spectra. They are lists of the format

spectrum 1 = {{x1,y11},{x2,y12},{x3,y13},...}
spectrum 2 = {{x1,y21},{x2,y22},{x3,y23},...}

I want to create a list with the original x-values, but the y-value being the y-value of list 1 + y-value of list 2 + ..., so in code:

result = {{x1,y11+y21},{x2,y12+y22},{x3,y13+y23},...}

Please notice that I will have approx. 50 lists that have to be added, not two.

Additional problem: Some of the lists have different length since they comprise a different wavelength-range. For example a list that doesn't start with x1:

list 7 = {{x4, y71},{x5,y72},{x6,y73},...}

Thanks.

m_goldberg
  • 107,779
  • 16
  • 103
  • 257
keyx
  • 353
  • 1
  • 7

3 Answers3

9
spectrum1 = {{x1, y11}, {x2, y12}, {x3, y13}, {x4, y14}, {x5, y15}};
spectrum2 = {{x1, y21}, {x2, y22}, {x3, y23}, {x4, y24}, {x5, y25}};
spectrum3 = {{x3, y33}, {x4, y34}, {x5, y35}};

GatherBy

{#[[All,1]][[1]],Total@#[[All,-1]]}&/@GatherBy[Join[spectrum1,spectrum2,spectrum3],First]

{{x1, y11 + y21}, {x2, y12 + y22}, {x3, y13 + y23 + y33},
{x4, y14 + y24 + y34}, {x5, y15 + y25 + y35}}

Merge

asso=Association@@Rule@@@#&/@{spectrum1,spectrum2,spectrum3};
List@@@Normal@Merge[asso, Total]

or

List@@@Normal@Merge[Total][Rule@@@Join[spectrum1,spectrum2,spectrum3]]

{{x1, y11 + y21}, {x2, y12 + y22}, {x3, y13 + y23 + y33},
{x4, y14 + y24 + y34}, {x5, y15 + y25 + y35}}

kglr
  • 394,356
  • 18
  • 477
  • 896
7

v10 only and using @kglr's spectra...

List @@@ Normal@
 GroupBy[Join[spectrum1, spectrum2, spectrum3], First -> Last, Total]

{{x1, y11 + y21}, {x2, y12 + y22}, {x3, y13 + y23 + y33}, {x4, y14 + y24 + y34}, {x5, y15 + y25 + y35}}

kale
  • 10,922
  • 1
  • 32
  • 69
  • I liked your solution very much. I did import the lists in a table, so that spectrum1=Dataset[[1]]. Can I now somehow loop inside the Join[...]-function, so that I don't explicitly have to write down all the list names in it? Thanks! – keyx Jun 25 '15 at 21:49
  • If your data is already in a Dataset, @kglr's Merge solution is probably the best. – kale Jun 25 '15 at 22:09
3

If they have the same length, one way would be using patterns. For example for 3 spectra:

spectrum1 = {{x1, y11}, {x2, y12}, {x3, y13}};
spectrum2 = {{x1, y21}, {x2, y22}, {x3, y23}};
spectrum3 = {{x1, y31}, {x2, y32}, {x3, y33}};

You write:

(spectrum1 + spectrum2 + spectrum3) /. {a_, b_} -> {a/3, b}

and you get:

{{x1, y11 + y21 + y31}, {x2, y12 + y22 + y32}, {x3, y13 + y23 + y33}}

If they don't have the same length, you can gather them based on first element, for example:

spectrum1 = {{x1, y11}, {x2, y12}, {x3, y13}};
spectrum2 = {{x1, y21}, {x2, y22}, {x3, y23}};
spectrum3 = {{x1, y31}, {x2, y32}, {x3, y33}};
spectrum7 = {{x4, y71}, {x5, y72}, {x6, y73}};


pts = GatherBy[Join[spectrum1, spectrum2, spectrum3, spectrum7], First]

to get:

{{{x1, y11}, {x1, y21}, {x1, y31}}, {{x2, y12}, {x2, y22}, {x2, 
 y32}}, {{x3, y13}, {x3, y23}, {x3, y33}}, {{x4, y71}}, {{x5, 
   y72}}, {{x6, y73}}} 

and finally:

 {First[#], Total@Rest[#]} & /@ (Union @@@ pts)
{{x1, y11 + y21 + y31}, {x2, y12 + y22 + y32}, {x3, 
 y13 + y23 + y33}, {x4, y71}, {x5, y72}, {x6, y73}}
Mahdi
  • 1,619
  • 10
  • 23
  • 1
    Using Union potentially leads to erroneous results, when actual spectra (with numerical values) are used. If, e.g., y23==y13, than one of them will get removed from the final result. – Karsten7 Jun 25 '15 at 21:19