python - examples - subplots
Matplotlib-Histograma escalonado con datos ya agrupados (4)
Estoy tratando de obtener un histograma con datos ya almacenados. He estado tratando de usar la bar()
para esto, pero parece que no puedo entender cómo hacer que sea un histograma escalonado como este a partir de los ejemplos , en lugar de un histograma lleno.
De la fuente que acompaña en http://matplotlib.sourceforge.net/examples/pylab_examples/histogram_demo_extended.html
Aquí es cómo dibujaron esa gráfica:
[recorte]
y el bit que quieres parece ser
pylab.hist(x, bins=bins, histtype=''step'')
^
right here
Edición: si desea saber cómo funciona hist (), mire la fuente: está definida en matplotlib / axes.py a partir de la línea 7407.
Mirando la línea 7724,
x = np.zeros( 2*len(bins), np.float )
y = np.zeros( 2*len(bins), np.float )
para N barras, las bandejas son un numpy.ndarray de N + 1 valores, que son los bordes para cada barra. Combinan los valores de cada barra (esto es lo que hace fraxel con np.ravel a continuación) y desplazan los puntos de datos a la mitad de una barra izquierda para centrarlos
x[0::2], x[1::2] = bins, bins
x -= 0.5*(bins[1]-bins[0])
establezca la altura de cada barra, hermanada pero desplazada en una (relativa a los valores de x) para producir el efecto de paso
# n is an array of arrays containing the number of items per bar
patches = [] # from line 7676
for m, c in zip(n, color):
y[1:-1:2], y[2::2] = m, m
patches.append(self.fill(x, y, closed=False, edgecolor=c, fill=False))
y el bit self.fill
es lo que realmente dibuja las líneas.
La solución más sencilla es convertir su conjunto de datos agrupado en un conjunto de datos ponderado no agrupado (con número de elementos == número de contenedores). El conjunto de datos no incorporados consistiría en valores de datos iguales a los centros del contenedor y ponderaciones iguales a los valores de cada contenedor. Por ejemplo, digamos que sus datos bineados son,
binedges = [0.0, 1.0, 2.0, 3.0]
ybinned = [11., 22., 33.]
El conjunto de datos ponderado correspondiente sería,
y = [0.5, 1.5, 2.5]
weights = [11., 22., 33.]
Tenga en cuenta que la opción de usar el centro del contenedor es arbitraria, puede usar cualquier punto dentro de un contenedor. Una vez que haya generado el conjunto de datos sin agrupar, puede usar el trazado normal del histograma de matplotlib (es decir, Axes.hist).
Una implementación de ejemplo en python sigue:
def plot_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)
Ahora puede tener acceso completo a todas las opciones de trazado de Axes.Histogram, incluido histtype="step"
para crear el histograma escalonado que deseaba.
Un ejemplo usando esta función sería,
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()
¡Espero que ayude!
Por alguna razón, la última bandeja no se cierra correctamente cuando lo intento. No se ve en las respuestas anteriores si se muestra la última línea, así que decidí hacer mi propia función, que hace lo que quiero.
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
Los 20
y 300
que se agregan son mi valor de binsize y final, respectivamente, y deben ajustarse si alguien quiere usar esto. x_input
y y_input
son los valores de np.histogram
de np.histogram
. Mi gráfico resultante (en azul el contorno, trazado con la función anterior. En rojo, el gráfico de barras de los mismos datos):
Puedes hacer trampa, compensando tus datos y usando la plot
lugar:
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'')
la trama: