¿Cómo trazar un histograma usando Matplotlib en Python con una lista de datos?

100

Estoy tratando de trazar un histograma usando la matplotlib.hist()función pero no estoy seguro de cómo hacerlo.

Tengo una lista

probability = [0.3602150537634409, 0.42028985507246375, 
  0.373117033603708, 0.36813186813186816, 0.32517482517482516, 
  0.4175257731958763, 0.41025641025641024, 0.39408866995073893, 
  0.4143222506393862, 0.34, 0.391025641025641, 0.3130841121495327, 
  0.35398230088495575]

y una lista de nombres (cadenas).

¿Cómo hago la probabilidad como mi valor y de cada barra y los nombres como valores x?

DataVizGuys
fuente

Respuestas:

168

Si desea un histograma, no necesita adjuntar ningún 'nombre' a los valores x, ya que en el eje x tendría contenedores de datos:

import matplotlib.pyplot as plt
import numpy as np
%matplotlib inline
np.random.seed(42)
x = np.random.normal(size=1000)
plt.hist(x, density=True, bins=30)  # `density=False` would make counts
plt.ylabel('Probability')
plt.xlabel('Data');

ingrese la descripción de la imagen aquí

Puede hacer que su histograma sea un poco más elegante con PDFlíneas, títulos y leyendas:

import scipy.stats as st
plt.hist(x, density=True, bins=30, label="Data")
mn, mx = plt.xlim()
plt.xlim(mn, mx)
kde_xs = np.linspace(mn, mx, 301)
kde = st.gaussian_kde(x)
plt.plot(kde_xs, kde.pdf(kde_xs), label="PDF")
plt.legend(loc="upper left")
plt.ylabel('Probability')
plt.xlabel('Data')
plt.title("Histogram");

ingrese la descripción de la imagen aquí

Sin embargo, si tiene un número limitado de puntos de datos, como en OP, un diagrama de barras tendría más sentido para representar sus datos (entonces puede adjuntar etiquetas al eje x):

x = np.arange(3)
plt.bar(x, height=[1,2,3])
plt.xticks(x, ['a','b','c'])

ingrese la descripción de la imagen aquí

Sergey Bushmanov
fuente
4
Recuerde, ¡no hay punto y coma al final de las líneas en python!
Toad22222
10
@ Toad22222 Este es un extracto de la celda del cuaderno Ipython. Intente ejecutarlo sin punto y coma y vea la diferencia. Todos los fragmentos de código que publico en SO se ejecutan perfectamente en mi computadora.
Sergey Bushmanov
2
Si se está preguntando sobre el punto y coma utilizado por Sergey, consulte aquí y el punto 16 aquí para ver cómo se utiliza el punto y coma en las celdas de los cuadernos de Jupyter (anteriormente, cuadernos de IPython) al trazar para suprimir el texto sobre el objeto de la trama.
Wayne
19

Si aún no ha instalado matplotlib, intente con el comando.

> pip install matplotlib

Importación de biblioteca

import matplotlib.pyplot as plot

Los datos del histograma:

plot.hist(weightList,density=1, bins=20) 
plot.axis([50, 110, 0, 0.06]) 
#axis([xmin,xmax,ymin,ymax])
plot.xlabel('Weight')
plot.ylabel('Probability')

Mostrar histograma

plot.show()

Y la salida es como:

ingrese la descripción de la imagen aquí

Niraj
fuente
2
La línea plot.axis ([50, 110, 0, 0.06]) 'es inútil para el ejemplo. Además, como codifica de forma difícil el área de la gráfica para mostrar, si sus datos no encajan completamente dentro de ella, puede confundirse por qué no se muestran correctamente.
typhon04
10

Aunque la pregunta parece exigir trazar un histograma usando la matplotlib.hist()función, podría decirse que no se puede hacer usando lo mismo, ya que la última parte de la pregunta exige usar las probabilidades dadas como los valores y de las barras y los nombres de pila (cadenas) como el valores x.

Estoy asumiendo una lista de muestra de nombres que corresponden a probabilidades dadas para dibujar la trama. Un diagrama de barras simple sirve aquí para el problema dado. Se puede utilizar el siguiente código:

import matplotlib.pyplot as plt
probability = [0.3602150537634409, 0.42028985507246375, 
  0.373117033603708, 0.36813186813186816, 0.32517482517482516, 
  0.4175257731958763, 0.41025641025641024, 0.39408866995073893, 
  0.4143222506393862, 0.34, 0.391025641025641, 0.3130841121495327, 
  0.35398230088495575]
names = ['name1', 'name2', 'name3', 'name4', 'name5', 'name6', 'name7', 'name8', 'name9',
'name10', 'name11', 'name12', 'name13'] #sample names
plt.bar(names, probability)
plt.xticks(names)
plt.yticks(probability) #This may be included or excluded as per need
plt.xlabel('Names')
plt.ylabel('Probability')
Shayan Shafiq
fuente
5

Esta es una pregunta antigua, pero ninguna de las respuestas anteriores ha abordado el problema real, es decir, el hecho de que el problema está en la pregunta en sí.

Primero, si las probabilidades ya se han calculado, es decir, los datos agregados del histograma están disponibles de manera normalizada, entonces las probabilidades deben sumar 1. Obviamente no es así y eso significa que algo anda mal aquí, ya sea con la terminología o con los datos. o en la forma en que se hace la pregunta.

En segundo lugar, el hecho de que se proporcionen las etiquetas (y no los intervalos) normalmente significaría que las probabilidades son de una variable de respuesta categórica, y lo mejor es utilizar un gráfico de barras para trazar el histograma (o alguna piratería del método hist del pyplot), La respuesta de Shayan Shafiq proporciona el código.

Sin embargo, vea el problema 1, esas probabilidades no son correctas y usar un diagrama de barras en este caso como "histograma" sería incorrecto porque no cuenta la historia de la distribución univariante, por alguna razón (quizás las clases se superponen y las observaciones se cuentan múltiples veces?) y dicho gráfico no debería llamarse histograma en este caso.

El histograma es, por definición, una representación gráfica de la distribución de una variable univariante (consulte https://www.itl.nist.gov/div898/handbook/eda/section3/histogra.htm , https://en.wikipedia.org/wiki / Histograma) y se crea dibujando barras de tamaños que representan recuentos o frecuencias de observaciones en clases seleccionadas de la variable de interés. Si la variable se mide en una escala continua, esas clases son contenedores (intervalos). Una parte importante del procedimiento de creación del histograma es elegir cómo agrupar (o mantener sin agrupar) las categorías de respuestas para una variable categórica, o cómo dividir el dominio de valores posibles en intervalos (dónde poner los límites del contenedor) para continuos. tipo de variable. Todas las observaciones deben estar representadas y cada una solo una vez en la trama. Eso significa que la suma de los tamaños de las barras debe ser igual al recuento total de observación (o sus áreas en el caso de los anchos variables, que es un enfoque menos común). O, si el histograma está normalizado, todas las probabilidades deben sumar 1.

Si los datos en sí son una lista de "probabilidades" como respuesta, es decir, las observaciones son valores de probabilidad (de algo) para cada objeto de estudio, entonces la mejor respuesta es simplemente plt.hist(probability)con la opción quizás de agrupamiento, y el uso de etiquetas x ya disponibles es suspicaz.

Entonces el diagrama de barras no debe usarse como histograma, sino simplemente

import matplotlib.pyplot as plt
probability = [0.3602150537634409, 0.42028985507246375, 
  0.373117033603708, 0.36813186813186816, 0.32517482517482516, 
  0.4175257731958763, 0.41025641025641024, 0.39408866995073893, 
  0.4143222506393862, 0.34, 0.391025641025641, 0.3130841121495327, 
  0.35398230088495575]
plt.hist(probability)
plt.show()

con los resultados

ingrese la descripción de la imagen aquí

matplotlib en tal caso llega por defecto con los siguientes valores de histograma

(array([1., 1., 1., 1., 1., 2., 0., 2., 0., 4.]),
 array([0.31308411, 0.32380469, 0.33452526, 0.34524584, 0.35596641,
        0.36668698, 0.37740756, 0.38812813, 0.39884871, 0.40956928,
        0.42028986]),
 <a list of 10 Patch objects>)

el resultado es una tupla de matrices, la primera matriz contiene recuentos de observaciones, es decir, lo que se mostrará contra el eje y del gráfico (suman 13, número total de observaciones) y la segunda matriz son los límites de intervalo para x -eje.

Se puede comprobar que estén igualmente espaciados,

x = plt.hist(probability)[1]
for left, right in zip(x[:-1], x[1:]):
  print(left, right, right-left)

ingrese la descripción de la imagen aquí

O, por ejemplo, para 3 contenedores (mi juicio requiere 13 observaciones) uno obtendría este histograma

plt.hist(probability, bins=3)

ingrese la descripción de la imagen aquí

con los datos de la trama "detrás de las rejas" siendo

ingrese la descripción de la imagen aquí

El autor de la pregunta debe aclarar cuál es el significado de la lista de valores de "probabilidad": la "probabilidad" es solo un nombre de la variable de respuesta (entonces, ¿por qué hay etiquetas x listas para el histograma? No tiene sentido ), o son los valores de la lista las probabilidades calculadas a partir de los datos (entonces el hecho de que no sumen 1 no tiene sentido).

predmod
fuente
4

Esta es una forma muy completa de hacerlo, pero si desea hacer un histograma en el que ya conoce los valores de bin pero no tiene los datos de origen, puede usar la np.random.randintfunción para generar el número correcto de valores dentro del rango de cada bin para graficar la función hist, por ejemplo:

import numpy as np
import matplotlib.pyplot as plt

data = [np.random.randint(0, 9, *desired y value*), np.random.randint(10, 19, *desired y value*), etc..]
plt.hist(data, histtype='stepfilled', bins=[0, 10, etc..])

en cuanto a las etiquetas, puede alinear x ticks con bins para obtener algo como esto:

#The following will align labels to the center of each bar with bin intervals of 10
plt.xticks([5, 15, etc.. ], ['Label 1', 'Label 2', etc.. ])
Connor Wilmers
fuente