2010-02-09 39 views
40

Me gustaría poder producir un gráfico de líneas apiladas (similar al método usado here) con Python (preferiblemente usando matplotlib, pero otra biblioteca también estaría bien). ¿Cómo puedo hacer esto?¿Cómo puedo crear un gráfico de líneas apiladas con matplotlib?

Esto es similar al stacked bar graph example en su sitio web, excepto que me gustaría que la parte superior de la barra se conecte con un segmento de línea y que se llene el área inferior. Podría ser capaz de aproximar esto disminuyendo las brechas entre barras y usando muchas barras (pero esto parece un truco, y además no estoy seguro de si es posible).

+5

El enlace en el ejemplo (http://www.whitehouse.gov/omb/budget/fy2003/images/bud20c.jpg) es roto. ¿Tienes un mejor enlace? –

+0

use stackplot() del paquete pyplot. – AjayKumarBasuthkar

+0

Esta es una vieja pregunta, pero para otras personas que encuentran esta pregunta en una búsqueda como yo, hay una nueva solución si estás usando data frames de pandas: 'df = pd.DataFrame (np.random.rand (10, 4), columnas = ['a', 'b', 'c', 'd']) ' ' df.plot.area(); 'desde http://pandas.pydata.org/pandas-docs/stable /visualization.html –

Respuesta

46

creo Área Terreno es un término común para este tipo de trama, y ​​en el caso específico citado en el OP, Área apilada Terreno.

Matplotlib no tiene una función de "out-of-the-box" que combina tanto el procesamiento de datos y la elaboración/procesamiento pasos para crear un este tipo de trama, pero es fácil de rodar su propia a partir de componentes suministrados por Matplotlib y NumPy.

El código de abajo primeras pilas los datos, después empates la trama.

import numpy as NP 
from matplotlib import pyplot as PLT 

# just create some random data 
fnx = lambda : NP.random.randint(3, 10, 10) 
y = NP.row_stack((fnx(), fnx(), fnx())) 
# this call to 'cumsum' (cumulative sum), passing in your y data, 
# is necessary to avoid having to manually order the datasets 
x = NP.arange(10) 
y_stack = NP.cumsum(y, axis=0) # a 3x10 array 

fig = PLT.figure() 
ax1 = fig.add_subplot(111) 

ax1.fill_between(x, 0, y_stack[0,:], facecolor="#CC6666", alpha=.7) 
ax1.fill_between(x, y_stack[0,:], y_stack[1,:], facecolor="#1DACD6", alpha=.7) 
ax1.fill_between(x, y_stack[1,:], y_stack[2,:], facecolor="#6E5160") 

PLT.show() 

example of stacked area plot

+13

Dado que intentas ser muy completo, ¿por qué no convertirlo en 'stackplot (x, yn, colorlist)' y archivar un error de solicitud de funciones en la parte superior? –

+0

Si desea crear una leyenda para este tipo de gráfico, creo que necesita utilizar proxy "Artistas" http://matplotlib.sourceforge.net/users/legend_guide.html#using-proxy-artist –

+1

@honk En realidad, ya hay un [pendiente de publicación] (https://github.com/matplotlib/matplotlib/pull/819) (que debería fusionarse pronto) para una función 'stackplot'. –

7

Una forma un poco menos hackish sería utilizar un gráfico de líneas en primer lugar y matplotlib.pyplot.fill_between. Para emular el apilamiento tienes que cambiar los puntos por ti mismo.

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') 
+0

¿Puedes explicar los parámetros del método fill_between()? parece que estamos rellenando un poco de color entre xey, pero ¿cuál es la tercera variable? – khan

+0

@khan: http://matplotlib.org/api/axes_api.html#matplotlib.axes.Axes.fill_between –

48

versiones más recientes de matplotlib contienen la función plt.stackplot, que permiten por varias diferentes parcelas de área "fuera-de-la-box" apiladas:

import numpy as np 
import pylab as plt 

X = np.arange(0, 10, 1) 
Y = X + 5 * np.random.random((5, X.size)) 

baseline = ["zero", "sym", "wiggle", "weighted_wiggle"] 
for n, v in enumerate(baseline): 
    plt.subplot(2 ,2, n + 1) 
    plt.stackplot(X, *Y, baseline=v) 
    plt.title(v) 
    plt.axis('tight') 
plt.show() 

Stack Plot using plt.stackplot.

+0

¿Qué significa '* Y'? –

2

Si tiene un marco de datos, es qui Te fácil:

df = pd.DataFrame(np.random.rand(10, 4), columns=['a', 'b', 'c', 'd']) 
df.plot.area(); 

enter image description here

Desde: pandas documentation

Cuestiones relacionadas