3
$\begingroup$

I'm trying to do interpolation on a large list of data of the format {{x1, y1}, {x2, y2}, {x3, y3}, ..., {xn, yn}} that is exported from a simulation.

Unfortunately, the exported data has some points {x_(i), y_(i)} and {x_(i + 1), y_(i + 1)} that share the same x point: x_(i) = x_(i + 1). This is just because of poor precision in the export process from the simulation.

The interpolation function doesn't like the fact that there are duplicate points that share the same x value, and gives me an error message with no output interpolation.

I want to take the duplicate points {x_(i), y_(i)} and {x_(i + 1), y_(i + 1)}, average y_(i) and y_(i + 1) and remove x_(i + 1) from the list. The final list should have no duplicates.

It should be pretty straightforward. I'm just a little slow at programming, because I don't have to do it very often.

$\endgroup$
1
  • $\begingroup$ Thanks guys! Both of these seem to work, and are more elegant than what I could have come up with. $\endgroup$ Feb 14, 2019 at 20:34

3 Answers 3

4
$\begingroup$

When the x-values are exact duplicates, the following might work (data is the n x 2 -matrix with the data points).

KeySort@GroupBy[data, First -> Last, Mean]

This produces an association. You may obtain a list again with

Transpose[ 
 Through[{Keys, Values}[
  KeySort@GroupBy[data, First -> Last, Mean]]
  ]
 ]
$\endgroup$
1
  • 1
    $\begingroup$ Or go straight to the list with data2 = {#[[1, 1]], Mean[#[[All, 2]]]} & /@ GatherBy[data, First] $\endgroup$
    – Bob Hanlon
    Feb 14, 2019 at 21:01
1
$\begingroup$
data = {{1, 2}, {3, 4}, {5, 6}, {1, 6}};

assocs = AssociationThread @* Apply[Rule] /@ data

<|1 -> 2|>, <|3 -> 4|>, <|5 -> 6|>, <|1 -> 6|>}

means = Merge[Mean][assocs]

<|1 -> 4, 3 -> 4, 5 -> 6|>

List @@@ Normal @ means

{{1, 4}, {3, 4}, {5, 6}}

$\endgroup$
0
$\begingroup$

How about this?

data = {{1, 2}, {3, 4}, {5, 6}, {1, 2}};

data2 = Union[data, SameTest -> (#1[[1]] == #2[[1]] &)]

(* {{1,2},{3,4},{5,6}} *)

If the x values are not exact duplicates then you can use:

SameTest -> (Abs[#1[[1]] - #2[[1]]] < minDifference &)

with minDifference set to an appropriate value.

$\endgroup$
1
  • $\begingroup$ My answer does not in fact average the y values. I voted for Henrick’s answer! $\endgroup$ Feb 14, 2019 at 21:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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