3
$\begingroup$

Suppose we have two lists:

data1 = {{1, 34}, {2, 54}, {3, 66}, {4, 77}, {5, 92}}
data2 = {{1, 1456}, {2, 1367}, {3, 2080}, {4, 1998}, {5, 1035}}

I'd like to create a new list such that

result = {{1, 34/1456}, {2, 54/1367}, {3, 66/2080}, {4, 77/1998}, {5, 92/1035}}

So, we only need to divide the second members of each pair; the first members remain unchanged.

$\endgroup$
  • 2
    $\begingroup$ You could use something like data1[[All, 2]] to extract the second parts of each pair, divide, and then use Transpose[] to reassemble. $\endgroup$ – J. M.'s technical difficulties May 18 at 16:53
6
$\begingroup$

If the elements appear in order:

MapThread[{First[#], Last[#]/Last[#2]} &, {data1, data2}]

If the elements may appear out of order (i.e. the first element in data1 may not correspond to the first element in data2):

{First[#], Last[#]/Last[#2]} & @@@ GatherBy[Join[data1, data2], First]

If they appear in order and you don't care about creating a variable or modifying an existing one:

data = data1; (* Creates a copy *)
data[[All, 2]] /= data2[[All, 2]];

Or if you want to use rules (this is mostly because we can - it's not necessarily something we should do):

ReplaceList[{data1, data2}, {
   {___, {i_, v1_}, ___},
   {___, {i_, v2_}, ___}
   } :> {i, v1/v2}]

This rule-based one works if the elements appear out order.

Here's another one:

List @@@ Normal[
  Association @@ Rule @@@ data1/Association @@ Rule @@@ data2
  ]

This has an object oriented feel to it and is for those that want to learn about UpValues:

f /: f[i_, j_]/f[i_, k_] := {i, j/k}
f @@@ data1/f @@@ data2
| improve this answer | |
$\endgroup$
  • 3
    $\begingroup$ awesome answer, my friend! There is much usefulness here for me to learn, and many nuances of usage displayed... Thank you for spending the time to share this with us all. $\endgroup$ – Francis from ResponseBase May 18 at 17:32
  • $\begingroup$ @FrancisfromResponseBase Thank you, I’m glad you found it useful! $\endgroup$ – C. E. May 18 at 19:29
4
$\begingroup$
Normal @ First @ Ratios[TimeSeries /@ {data2, data1}] 
 {{1, 17/728}, {2, 54/1367}, {3, 33/1040}, {4, 77/1998}, {5, 4/45}}

Or define a function:

ClearAll[rF]
rF = Normal @* First @* Ratios @* Map[TimeSeries] @* Reverse;

rF @ {data1, data2}

enter image description here

Normal@ rF @ {data1, data2}

{{1, 17/728}, {2, 54/1367}, {3, 33/1040}, {4, 77/1998}, {5, 4/45}}

Or use the property "Path":

rF[{data1, data2}]["Path"]
 {{1, 17/728}, {2, 54/1367}, {3, 33/1040}, {4, 77/1998}, {5, 4/45}}
| improve this answer | |
$\endgroup$
3
$\begingroup$

as J.M suggested, you can write

Transpose[{data1[[;; , 1]],data1[[;; , 2]] / data2[[;; , 2]]}]

updated: removed Thread

| improve this answer | |
$\endgroup$
  • 1
    $\begingroup$ (+1) Or, as a 'just for fun' alternative: Transpose[{data1.{1,0},data1.{0,1}/data2.{0,1}}] $\endgroup$ – user1066 May 18 at 17:38

Your Answer

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

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