views:

519

answers:

2

I would like to be able to produce a stacked line graph (similar to the method used here) with Python (preferably using matplotlib, but another library would be fine too). How can I do this?

This similar to the stacked bar graph example on their website, except I'd like the top of bar to be connected with a line segment and the area underneath to be filled. I might be able to approximate this by decreasing the gaps between bars and using lots of bars (but this seems like a hack, and besides I'm not sure if it is possible).

+2  A: 

A slightly less hackish way would be to use a line graph in the first place and matplotlib.pyplot.fill_between. To emulate the stacking you have to shift the points up yourself.

x = np.arange(0,4)
y1 = np.array([1,2,4,3])
y2 = np.array([5,2,1,3])
# y2 should go on top, so shift them up
y2s = y1+y2

plot(x,y1)
plot(x,y2s)
fill_between(x,y1,0,color='blue')
fill_between(x,y1,y2s,color='red')
honk
+5  A: 

The code below will "stack" the data for you--no additional input is necessary after you pass in your data.

After stacking the data, it draws the plot.

(As an aside: I was trying to find the generally accepted name for this type of plot. As you can see below, Matplotlib is quite good at drawing them, but it doesn't have a name for them (nor obviously a separate convenience function). One of R's plotting libraries refers to this format as an "area plots". In addition, these plots look like 'density plots' but they're not--the convention seems to be that multiple density plots (more than one series plotted on the same axis) refer to overlaid rather than stacked data (multiple histogram series are stacked by convention though).

import numpy as NP
from matplotlib import pyplot as PLT
# just create some random data
fnx = lambda : NP.random.randint(3, 10, 10)
x = NP.arange(0, 10)
y1 = fnx()
y2 = fnx()
y3 = fnx()
y_data = NP.row_stack((y1, y2, y3))
# this call to 'cumsum' (cumulative sum), passing in your y data, is important to
# avoid having to manually order the datasets 
y_data_stacked = NP.cumsum(y_data, axis=0)
fig = PLT.figure()
ax1 = fig.add_subplot(111)
ax1.fill_between(x, 0, y_data_stacked[0,:], facecolor="#CC6666", alpha=0.7)
ax1.fill_between(x, y_data_stacked[0,:], y_data_stacked[1,:], facecolor="#1DACD6", 
alpha=0.7)
ax1.fill_between(x, y_data_stacked[1,:], y_data_stacked[2,:], facecolor="#6E5160")
PLT.show()

The Result:

doug
Since you are trying to be very complete why not turn that into `stackplot(x,yn,colorlist)` and file a feature request bug upstream?
honk