2
$\begingroup$

So I'm trying to generate an interpolation function from a bode plot (log-log plot) by extracting the graph data using mathematica. I've got to the point where I was able to isolate only the curve I am interested in (black/white image), and generate a list of points from there. However, my list has a few y-values for each x-value, and so the interpolation function does not work. I want to average these values and compress them into a single point.

My list is of the form

exampleList={{10, 100}, {10, 1000}, {15, 200} ... }

and what I want is

newList={{10, 550}, {15, 200} ... }

where 550 is the arithmetic mean of 100 and 1000.

I'm a C programmer and I could write the whole thing with a couple of Do[] and If[]'s, but I'm trying to learn how to use Mathematica, not C.

Bode plot for gain and phaseenter image description here

$\endgroup$

2 Answers 2

2
$\begingroup$

Here are two possible approaches for doing that:

  • SequenceCases (for a first-element sorted list):

    SequenceCases[exampleList, {args : {x_, _} ..} :> {x, Mean[{args}[[All, 2]]]}]
    
  • GroupBy and KeyValueMap:

    (* a first possibility *)
    KeyValueMap[{#1, Mean[#2]} &, GroupBy[exampleList, First -> Last]]
    
    (* equivalent *)
    KeyValueMap[{#1, #2} &, GroupBy[exampleList, First -> Last, Mean]]
    
$\endgroup$
2
  • $\begingroup$ SequenceCases[] worked like a charm! The notation is still a little opaque to me, though. What's the purpose of using a delayed rule here? $\endgroup$
    – Jordan
    Sep 8, 2016 at 21:44
  • $\begingroup$ It avoids the evaluation of the right-hand side. This is in particular useful if x and args where defined elsewhere during the same session. For instance, you can try: x = 3; args = {0, 0}; SequenceCases[exampleList, {args : {x_, _} ..} -> {x, Mean[{args}[[All, 2]]]}], and the same with RuleDelayed. Using the latter, you make sure that these two arguments are bound to the left-hand side of the rule. $\endgroup$
    – user31159
    Sep 8, 2016 at 21:55
1
$\begingroup$
lst = {{1, 1}, {1, 2}, {2, 1}, {2, 2}, {2, 3}, {2, 4}}

Then

lst // GroupBy[First] // KeyValueMap[ {#1, N@Mean@#2[[All, 2]]} &]

or

GatherBy[lst, First] // Map[{#[[1, 1]], N@Mean@#[[All, 2]]} &]

both return

(* {{1, 1.5}, {2, 2.5}} *)
$\endgroup$

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.