Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I have a 2D dataset like this one: {{x1,y1}, {x2,y2},...} I need to smooth/histogram the data in such a way that binning is over the x-coordinate, while counting/height is over the y-coordinate. Let me explain.

Given the following input, bin-width=0.2 and height-function=Mean[].

data = {{0.1,1.0}, {0.2,2.0}, {0.3,3.0}, {0.35,3.5}, {0.4,4.0}, {0.5,5.0}};

The output would be:

{(1 + 2)/2, (3 + 3.5 + 4)/3, 5/1}

The average of y-values from the first two data points goes into the first bin, the following three points form the second bin etc...

share|improve this question
add comment

3 Answers 3

up vote 6 down vote accepted

Let's start with your sample data:

In[1]:= data = {{0.1, 1.0}, {0.2, 2.0}, {0.3, 3.0}, {0.35, 3.5}, {0.4, 4.0}, {0.5, 5.0}};

First we can use GatherBy to group entries by bin:

In[2]:= GatherBy[data, Ceiling[First[#], 0.2] &]

Out[2]= {{{0.1, 1.}, {0.2, 2.}}, {{0.3, 3.}, {0.35, 3.5}, {0.4, 4.}}, {{0.5, 5.}}}

Then select the second element of each pair (Last) and calculate the means:

In[3]:= Mean[Last /@ #] & /@ %

Out[3]= {1.5, 3.5, 5.}
share|improve this answer
    
This method groups elements 0.29 and 0.31 -- shouldn't these be in separate bins? –  Mr.Wizard May 7 '12 at 19:35
    
@Mr.Wizard No, because with a bin size of 0.2 everything between 0.2 and 0.4 should be in the same bin. I just realized though that $MachineEpsilon is too small a number to add here if the $x$-values are greater than 1. (I added a note about this.) –  Szabolcs May 7 '12 at 19:37
    
If that is the intent couldn't you use Ceiling[#, 0.2]? –  Mr.Wizard May 7 '12 at 19:39
    
@Mr.Wizard Yes, you are right, I fixed it. –  Szabolcs May 7 '12 at 19:44
    
Voted. If the OP actually wants bins to 0.1, 0.3, 0.5 which was my own reading, this is more complicated I think. –  Mr.Wizard May 7 '12 at 19:45
show 1 more comment

I propose:

data = {{0.1, 1.0}, {0.2, 2.0}, {0.3, 3.0}, {0.35, 3.5}, {0.4, 4.0}, {0.5, 5.0}};

Mean /@ Reap[#2 ~Sow~ Ceiling[#, 0.2] & @@@ data][[2]]
{1.5, 3.5, 5.}
share|improve this answer
    
+1 I had almost forgotten the "~ ~ ~ ~ " war :) –  belisarius May 7 '12 at 19:59
    
@belisarius I actually started without that but then I decided to keep up my end of the game. :^) –  Mr.Wizard May 7 '12 at 20:01
add comment

Another offering making use of BinLists:

data = {{0.1, 1.0}, {0.2, 2.0}, {0.3, 3.0}, {0.35, 3.5}, {0.4, 
    4.0}, {0.5, 5.0}};

Smoothed[data_, binSize_] := 
 With[{xs = data\[Transpose] // First, ys = data\[Transpose] // Last},
   Mean@ys[[#]] & /@ (Flatten[Map[Position[xs, #] &, #]] & /@ 
     BinLists[xs, 0.2 + $MachineEpsilon])]

Smoothed[data, 0.2]

(* ->  {1.5, 3.5, 5.}  *)
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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