Como plotar um histograma usando Matplotlib em Python com uma lista de dados?

98

Estou tentando plotar um histograma usando a matplotlib.hist()função, mas não tenho certeza de como fazer isso.

Eu tenho uma 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]

e uma lista de nomes (strings).

Como faço a probabilidade como meu valor y de cada barra e nomes como valores x?

DataVizGuys
fonte

Respostas:

167

Se você quiser um histograma, não precisa anexar nenhum 'nome' aos valores x, pois no eixo x você teria caixas de dados:

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');

insira a descrição da imagem aqui

Você pode deixar seu histograma um pouco mais elaborado com PDFlinhas, títulos e legendas:

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");

insira a descrição da imagem aqui

No entanto, se você tiver um número limitado de pontos de dados, como em OP, um gráfico de barra faria mais sentido para representar seus dados (então você pode anexar rótulos ao eixo x):

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

insira a descrição da imagem aqui

Sergey Bushmanov
fonte
4
Lembre-se, nenhum ponto-e-vírgula no final das linhas em python!
Toad22222
10
@ Toad22222 Este é um trecho da célula do notebook Ipython. Tente executá-lo sem ponto-e-vírgula e veja a diferença. Todos os trechos de código que posto no SO rodam perfeitamente no meu computador.
Sergey Bushmanov de
2
Se você está se perguntando sobre o ponto-e-vírgula usado por Sergey, veja aqui e # 16 aqui para saber como o ponto-e-vírgula é usado em células de blocos de notas Jupyter (anteriormente blocos de notas IPython) ao plotar para suprimir o texto sobre o objeto de plotagem.
Wayne
19

Se você ainda não instalou o matplotlib, tente o comando.

> pip install matplotlib

Importação de biblioteca

import matplotlib.pyplot as plot

Os dados do 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')

Exibir histograma

plot.show()

E a saída é como:

insira a descrição da imagem aqui

Niraj
fonte
2
A linha plot.axis ([50, 110, 0, 0,06]) 'é inútil para o exemplo. Além disso, como é difícil codificar a área do gráfico para mostrar, se seus dados não couberem inteiramente dentro dele, você pode ficar confuso porque eles não aparecem corretamente.
typhon04 de
8

Embora a questão pareça estar exigindo traçar um histograma usando a matplotlib.hist()função, pode-se argumentar que não pode ser feito usando o mesmo que a última parte da questão exige o uso das probabilidades fornecidas como os valores y das barras e os nomes dados (strings) como o valores x.

Estou assumindo uma lista de exemplos de nomes correspondentes a determinadas probabilidades para desenhar o gráfico. Um gráfico de barra simples serve ao propósito aqui para o problema fornecido. O seguinte código pode ser usado:

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
fonte
4

Esta é uma maneira bastante circular de fazer isso, mas se você quiser fazer um histograma onde já conhece os valores bin, mas não tem os dados de origem, você pode usar a np.random.randintfunção para gerar o número correto de valores dentro do intervalo de cada bin para a função hist representar graficamente, por exemplo:

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..])

quanto aos rótulos, você pode alinhar x ticks com bins para obter algo assim:

#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
fonte
3

Esta é uma questão antiga, mas nenhuma das respostas anteriores abordou o problema real, ou seja, o fato de que o problema é com a própria questão.

Primeiro, se as probabilidades já foram calculadas, ou seja, os dados agregados do histograma estão disponíveis de forma normalizada, então as probabilidades deveriam somar 1. Elas obviamente não somam e isso significa que algo está errado aqui, seja com a terminologia ou com os dados ou na forma como a pergunta é feita.

Em segundo lugar, o fato de que os rótulos são fornecidos (e não intervalos) normalmente significaria que as probabilidades são de variável de resposta categórica - e o uso de um gráfico de barra para traçar o histograma é o melhor (ou algum hackeamento do método hist do pyplot), A resposta de Shayan Shafiq fornece o código.

No entanto, consulte o problema 1, essas probabilidades não estão corretas e usar o gráfico de barras neste caso como "histograma" seria errado porque não conta a história da distribuição univariada, por algum motivo (talvez as classes estão sobrepostas e as observações são contadas múltiplas vezes?) e esse gráfico não deve ser chamado de histograma neste caso.

O histograma é, por definição, uma representação gráfica da distribuição da variável univariada (consulte https://www.itl.nist.gov/div898/handbook/eda/section3/histogra.htm , https://en.wikipedia.org/wiki / Histograma) e é criado desenhando barras de tamanhos que representam contagens ou frequências de observações em classes selecionadas da variável de interesse. Se a variável for medida em uma escala contínua, essas classes são bins (intervalos). Parte importante do procedimento de criação de histograma é fazer a escolha de como agrupar (ou manter sem agrupar) as categorias de respostas para uma variável categórica, ou como dividir o domínio de valores possíveis em intervalos (onde colocar os limites do compartimento) para contínuos variável de tipo. Todas as observações devem ser representadas, e cada uma apenas uma vez na parcela. Isso significa que a soma dos tamanhos das barras deve ser igual à contagem total de observação (ou suas áreas no caso de larguras variáveis, que é uma abordagem menos comum). Ou, se o histograma for normalizado, todas as probabilidades devem somar 1.

Se os dados em si são uma lista de "probabilidades" como uma resposta, ou seja, as observações são valores de probabilidade (de algo) para cada objeto de estudo, então a melhor resposta é simplesmente plt.hist(probability)com a opção talvez binning, e o uso de rótulos x já disponíveis é suspeito.

Então o gráfico de barra não deve ser usado como histograma, mas simplesmente

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()

com os resultados

insira a descrição da imagem aqui

matplotlib, nesse caso, chega por padrão com os seguintes 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>)

o resultado é uma tupla de matrizes, a primeira matriz contém contagens de observação, ou seja, o que será mostrado contra o eixo y do gráfico (somam 13, número total de observações) e a segunda matriz são os limites de intervalo para x -eixo.

Pode-se verificar se eles estão igualmente espaçados,

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

insira a descrição da imagem aqui

Ou, por exemplo, para 3 bins (minha opinião é de 13 observações), obter-se-ia este histograma

plt.hist(probability, bins=3)

insira a descrição da imagem aqui

com os dados do gráfico "atrás das barras" sendo

insira a descrição da imagem aqui

O autor da pergunta precisa esclarecer qual é o significado da lista de valores de "probabilidade" - é a "probabilidade" apenas um nome da variável de resposta (então por que existem rótulos x prontos para o histograma, não faz sentido ), ou os valores da lista são as probabilidades calculadas a partir dos dados (então, o fato de eles não somarem 1 não faz sentido).

predmod
fonte