pythonnumpymatplotlibseabornecdf

How to plot empirical CDF (ECDF)


How can I plot the empirical CDF of an array of numbers with Matplotlib in Python? I'm looking for the CDF analog of Pylab’s hist function.

One thing I can think of is:

from scipy.stats import cumfreq
a = array([...]) # my array of numbers
num_bins =  20
b = cumfreq(a, num_bins)
plt.plot(b)

Solution

  • That looks to be (almost) exactly what you want. Two things:

    First, the results are a tuple of four items. The third is the size of the bins. The second is the starting point of the smallest bin. The first is the number of points in the in or below each bin. (The last is the number of points outside the limits, but since you haven't set any, all points will be binned.)

    Second, you'll want to rescale the results so the final value is 1, to follow the usual conventions of a CDF, but otherwise it's right.

    Here's what it does under the hood:

    def cumfreq(a, numbins=10, defaultreallimits=None):
        # docstring omitted
        h,l,b,e = histogram(a,numbins,defaultreallimits)
        cumhist = np.cumsum(h*1, axis=0)
        return cumhist,l,b,e
    

    It does the histogramming, then produces a cumulative sum of the counts in each bin. So the ith value of the result is the number of array values less than or equal to the the maximum of the ith bin. So, the final value is just the size of the initial array.

    Finally, to plot it, you'll need to use the initial value of the bin, and the bin size to determine what x-axis values you'll need.

    Another option is to use numpy.histogram which can do the normalization and returns the bin edges. You'll need to do the cumulative sum of the resulting counts yourself.

    a = array([...]) # your array of numbers
    num_bins = 20
    counts, bin_edges = numpy.histogram(a, bins=num_bins, normed=True)
    cdf = numpy.cumsum(counts)
    pylab.plot(bin_edges[1:], cdf)
    

    (bin_edges[1:] is the upper edge of each bin.)