7
$\begingroup$

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.

$\endgroup$
0

3 Answers 3

7
$\begingroup$

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

$\endgroup$
2
  • $\begingroup$ 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! $\endgroup$
    – keyx
    Jun 25, 2015 at 21:49
  • $\begingroup$ If your data is already in a Dataset, @kglr's Merge solution is probably the best. $\endgroup$
    – kale
    Jun 25, 2015 at 22:09
9
$\begingroup$
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}}

$\endgroup$
3
$\begingroup$

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}}
$\endgroup$
1
  • 1
    $\begingroup$ 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. $\endgroup$
    – Karsten7
    Jun 25, 2015 at 21:19

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