Skip to content Skip to sidebar Skip to footer

Matplotlib - Stepped Histogram With Already Binned Data

I am trying to get a histogram with already binned data. I have been trying to use bar() for this, but I can't seem to figure out how to make it a stepped histogram like this one f

Solution 1:

You could cheat, by offsetting your data and using plot instead:

from matplotlib import pyplot
import numpy as np

#sample data:
x = np.arange(30)
y = np.cumsum(np.arange(30))
#offset the x for horizontal, repeat the y for vertical:
x = np.ravel(zip(x,x+1))
y = np.ravel(zip(y,y))

pyplot.plot(x,y)
pyplot.savefig('plt.png')

the plot:

enter image description here

Solution 2:

The simplest solution is to convert your binned dataset to an un-binned, weighted dataset (with number of elements == number of bins). The unbinned dataset would consist of data values equal to the bin centres and weights equal to the values in each bin. For example let's say that your binned data is,

binedges = [0.0, 1.0, 2.0, 3.0]
ybinned = [11., 22., 33.]

The corresponding weighted dataset would be,

y =       [0.5, 1.5, 2.5]
weights = [11., 22., 33.]

Note that the choice to use the bin centre is arbitrary, you could use any point within a bin. Once you have generated the un-binned dataset then you can use the normal matplotlib histogram plotting (i.e. Axes.hist).

An example implementation in python follows:

defplot_binned_data(axes, binedges, data,
               *args, **kwargs):
    #The dataset values are the bin centres
    x = (binedges[1:] + binedges[:-1]) / 2.0#The weights are the y-values of the input binned data
    weights = data
    return axes.hist(x, bins=binedges, weights=weights,
               *args, **kwargs)

You can now have full access to all of the Axes.Histogram plotting options, including histtype="step" to create the stepped histogram that you wanted.

An example using this function would be,

import numpy
import matplotlib.pyplot as plt

#Create a dataset
dataset = numpy.random.normal(size=100)
#Bin the dataset
binedges = numpy.linspace(-5.0, 5.0, num=10)
y, binedges = numpy.histogram(dataset, binedges)

#Plot the dataset
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
plot_binned_data(ax, binedges, y, histtype="step")
plt.show()

Hope that helps!

Solution 3:

From the accompanying source at http://matplotlib.sourceforge.net/examples/pylab_examples/histogram_demo_extended.html

here is how they drew that graph:

[snip]

and the bit you want appears to be

pylab.hist(x, bins=bins, histtype='step')
                            ^
                        right here

Edit: if you want to know how hist() works, look at the source - it's defined in matplotlib/axes.py starting at line 7407.

Looking at line 7724,

x = np.zeros( 2*len(bins), np.float )
y = np.zeros( 2*len(bins), np.float )

for N bars, bins is an numpy.ndarray of N+1 values, being the edges for each bar. They twin the values for each bar (this is what fraxel is doing with np.ravel below) and shift the datapoints half a bar left to center them

x[0::2], x[1::2] = bins, bins
x -= 0.5*(bins[1]-bins[0])

set the height of each bar, twinned but offset by one (relative to the x values) to produce the step effect

# n is an array of arrays containing the number of items per bar
patches = []    # from line 7676for m, c inzip(n, color):
    y[1:-1:2], y[2::2] = m, m
    patches.append(self.fill(x, y, closed=False, edgecolor=c, fill=False))

and the self.fill bit is what actually draws the lines.

Solution 4:

For some reason, the last bin isn't properly closed when I try it. It is not visible from the previous answers if the last line is showed, so I decided to make my own function, which does what I want.

def make_bar_contour_plot(ax,x_input,y_input):

    x = list(np.ravel(zip(x_input[:-1],x_input[:-1]+1)))[1:]
    x += [x[-1]+20] + [300] 
    y = list(np.ravel(zip(y_input,y_input))) +[0]
    ax.plot(x,y,ls='steps')

    return ax

The 20 and 300 that are added are my binsize and ending value respectively, and need to be adjusted if anyone wants to use this. x_input and y_input are the returning values from np.histogram. My resulting plot (in blue the contour, plotted with above function. In red, the barplot of the same data):

My result in contourplotting a histogram

Post a Comment for "Matplotlib - Stepped Histogram With Already Binned Data"