Estoy usando matplotlib para hacer un histograma.
¿Hay alguna forma de establecer manualmente el tamaño de los contenedores en lugar del número de contenedores?
Estoy usando matplotlib para hacer un histograma.
¿Hay alguna forma de establecer manualmente el tamaño de los contenedores en lugar del número de contenedores?
Respuestas:
En realidad, es bastante fácil: en lugar del número de contenedores, puede dar una lista con los límites del contenedor. También se pueden distribuir de manera desigual:
plt.hist(data, bins=[0, 10, 20, 30, 40, 50, 100])
Si solo desea que se distribuyan por igual, simplemente puede usar el rango:
plt.hist(data, bins=range(min(data), max(data) + binwidth, binwidth))
Agregado a la respuesta original
La línea anterior funciona solo para data
números enteros. Como señala el macrocosmos , para las carrozas puedes usar:
import numpy as np
plt.hist(data, bins=np.arange(min(data), max(data) + binwidth, binwidth))
(data.max() - data.min()) / number_of_bins_you_want
. Se + binwidth
podría cambiar a solo 1
para hacer de este un ejemplo más fácil de entender.
lw = 5, color = "white"
o similar inserta espacios en blanco entre las barras
Para N bins, los bordes del bin se especifican mediante una lista de valores de N + 1 donde el primer N da los bordes inferiores del bin y el +1 da el borde superior del último bin.
Código:
from numpy import np; from pylab import *
bin_size = 0.1; min_edge = 0; max_edge = 2.5
N = (max_edge-min_edge)/bin_size; Nplus1 = N + 1
bin_list = np.linspace(min_edge, max_edge, Nplus1)
Tenga en cuenta que linspace produce una matriz de min_edge a max_edge dividida en valores N + 1 o N bins
Supongo que la manera fácil sería calcular el mínimo y el máximo de los datos que tiene, luego calcular L = max - min
. Luego se divide L
por el ancho del contenedor deseado (supongo que esto es lo que quiere decir con el tamaño del contenedor) y usa el límite máximo de este valor como el número de contenedores.
Me gusta que las cosas sucedan automáticamente y que los contenedores caigan en valores "agradables". Lo siguiente parece funcionar bastante bien.
import numpy as np
import numpy.random as random
import matplotlib.pyplot as plt
def compute_histogram_bins(data, desired_bin_size):
min_val = np.min(data)
max_val = np.max(data)
min_boundary = -1.0 * (min_val % desired_bin_size - min_val)
max_boundary = max_val - max_val % desired_bin_size + desired_bin_size
n_bins = int((max_boundary - min_boundary) / desired_bin_size) + 1
bins = np.linspace(min_boundary, max_boundary, n_bins)
return bins
if __name__ == '__main__':
data = np.random.random_sample(100) * 123.34 - 67.23
bins = compute_histogram_bins(data, 10.0)
print(bins)
plt.hist(data, bins=bins)
plt.xlabel('Value')
plt.ylabel('Counts')
plt.title('Compute Bins Example')
plt.grid(True)
plt.show()
El resultado tiene contenedores en intervalos agradables de tamaño de contenedor.
[-70. -60. -50. -40. -30. -20. -10. 0. 10. 20. 30. 40. 50. 60.]
desired_bin_size=0.05
, min_boundary=0.850
, max_boundary=2.05
el cálculo de los n_bins
convierte en int(23.999999999999993)
los cuales los resultados en 23 en lugar de 24 y, por tanto, una bandeja muy pocos. Un redondeo antes de la conversión de enteros funcionó para mí:n_bins = int(round((max_boundary - min_boundary) / desired_bin_size, 0)) + 1
Utilizo cuantiles para hacer contenedores uniformes y ajustados a la muestra:
bins=df['Generosity'].quantile([0,.05,0.1,0.15,0.20,0.25,0.3,0.35,0.40,0.45,0.5,0.55,0.6,0.65,0.70,0.75,0.80,0.85,0.90,0.95,1]).to_list()
plt.hist(df['Generosity'], bins=bins, normed=True, alpha=0.5, histtype='stepfilled', color='steelblue', edgecolor='none')
np.arange(0, 1.01, 0.5)
o np.linspace(0, 1, 21)
. No hay bordes, pero entiendo que las cajas tienen el mismo área, pero diferente ancho en el eje X?
Tuve el mismo problema que OP (¡creo!), Pero no pude hacer que funcionara de la manera que Lastalda especificó. No sé si he interpretado la pregunta correctamente, pero he encontrado otra solución (aunque probablemente sea una forma realmente mala de hacerlo).
Así fue como lo hice:
plt.hist([1,11,21,31,41], bins=[0,10,20,30,40,50], weights=[10,1,40,33,6]);
Lo que crea esto:
Entonces, el primer parámetro básicamente 'inicializa' el bin: específicamente estoy creando un número que está entre el rango que configuré en el parámetro bins.
Para demostrar esto, observe la matriz en el primer parámetro ([1,11,21,31,41]) y la matriz 'bins' en el segundo parámetro ([0,10,20,30,40,50]) :
Luego estoy usando el parámetro 'pesos' para definir el tamaño de cada contenedor. Esta es la matriz utilizada para el parámetro de pesos: [10,1,40,33,6].
Entonces, el bin de 0 a 10 recibe el valor 10, el bin de 11 a 20 recibe el valor de 1, el bin de 21 a 30 recibe el valor de 40, etc.
Para un histograma con valores x enteros, terminé usando
plt.hist(data, np.arange(min(data)-0.5, max(data)+0.5))
plt.xticks(range(min(data), max(data)))
El desplazamiento de 0.5 centra los bins en los valores del eje x. La plt.xticks
llamada agrega una marca para cada número entero.