Tamanho da bandeja no Matplotlib (histograma)


149

Estou usando o matplotlib para fazer um histograma.

Existe alguma maneira de definir manualmente o tamanho dos compartimentos em oposição ao número de compartimentos?

Respostas:


270

Na verdade, é bem fácil: em vez do número de posições, você pode fornecer uma lista com os limites da posição. Eles também podem ser distribuídos de forma desigual:

plt.hist(data, bins=[0, 10, 20, 30, 40, 50, 100])

Se você apenas deseja distribuí-los igualmente, basta usar o range:

plt.hist(data, bins=range(min(data), max(data) + binwidth, binwidth))

Adicionado à resposta original

A linha acima funciona apenas para datanúmeros inteiros. Como o macrocosme aponta, para carros alegóricos você pode usar:

import numpy as np
plt.hist(data, bins=np.arange(min(data), max(data) + binwidth, binwidth))

20
substitua o intervalo (...) pelo np.arange (...) para que ele funcione com flutuadores.
— Macrocosme

6
qual é a largura de caixa aqui? você definiu esse valor antes?
— usar o seguinte comando

1
Acredito binwidth neste exemplo poderia ser encontrado por: (data.max() - data.min()) / number_of_bins_you_want. A + binwidthpode ser alterado para apenas 1para tornar este um exemplo mais facilmente compreendido.
— Jarad 22/0118

2
Além da excelente solução do CodingCat acima, para dados flutuantes, se você quiser que as barras do histograma sejam centradas em torno de x-ticks inteiros em vez de ter os limites da barra nos x-ticks, tente o seguinte ajuste: bins = np.arange (dmin - 0.5, dmax + 0.5 + binwidth, binwidth)
— DaveW 13/08

3
opcionais lw = 5, color = "white"ou semelhantes inserções de espaços em branco entre barras
— PatrickT

13

Para os compartimentos N, as bordas da bandeja são especificadas pela lista de valores N + 1, onde o primeiro N fornece as bordas inferiores da bandeja e o +1 fornece a borda superior da última bandeja.

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)

Observe que o linspace produz uma matriz de min_edge a max_edge dividida em valores N + 1 ou N bins


1
Observe que os compartimentos incluem seu limite inferior e excluem seu limite superior, com exceção do compartimento N + 1 (último), que inclui os dois limites.
— Lukewitmer 01/03

4

Eu acho que a maneira mais fácil seria calcular o mínimo e o máximo dos dados que você possui e depois calcular L = max - min. Em seguida, você divide Lpela largura desejada da lixeira (suponho que isso seja o que você quer dizer com tamanho da lixeira) e usa o teto desse valor como o número de lixeiras.


isso é exatamente o que eu tinha em mente, obrigado. Só queria saber se havia uma maneira mais simples, mas isso parece encontrar obrigado!
— Sam Creamer

Usando números redondos, não tenho tamanho de lixeira redonda com essa abordagem. Alguém experimentou isso?
— amigos estão dizendo sobre bruno urani

3

Eu gosto que as coisas aconteçam automaticamente e que as caixas caiam em valores "agradáveis". O seguinte parece funcionar muito bem.

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

O resultado possui compartimentos em intervalos agradáveis ​​de tamanho de compartimento.

[-70. -60. -50. -40. -30. -20. -10.   0.  10.  20.  30.  40.  50.  60.]

histograma de caixas computadas


Exatamente o que eu estava procurando! No entanto, em alguns casos, os n_bins são arredondados para baixo devido à precisão do ponto flutuante. Por exemplo, para desired_bin_size=0.05, min_boundary=0.850, max_boundary=2.05o cálculo de n_binsse torna int(23.999999999999993)o que resulta em 23 em vez de 24, e, por conseguinte, um bin muito poucos. Um arredondamento antes da conversão de número inteiro funcionou para mim:n_bins = int(round((max_boundary - min_boundary) / desired_bin_size, 0)) + 1
— M. Schlenker

3

Eu uso quantis para fazer caixas uniformes e ajustadas à amostra:

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

insira a descrição da imagem aqui


1
Boa ideia. Você pode substituir a lista de quantis por np.arange(0, 1.01, 0.5)ou np.linspace(0, 1, 21). Não há arestas, mas entendo que as caixas têm área igual, mas largura diferente no eixo X?
— Tomasz Gandor 13/06

2

Eu tive o mesmo problema do OP (acho!), Mas não consegui fazê-lo funcionar da maneira especificada pela Lastalda. Não sei se interpretei a pergunta corretamente, mas encontrei outra solução (provavelmente é uma maneira muito ruim de fazer isso).

Foi assim que eu fiz:

plt.hist([1,11,21,31,41], bins=[0,10,20,30,40,50], weights=[10,1,40,33,6]);

O que cria isso:

imagem mostrando o gráfico do histograma criado no matplotlib

Portanto, o primeiro parâmetro basicamente 'inicializa' a lixeira - estou criando especificamente um número que está entre o intervalo que eu defini no parâmetro bins.

Para demonstrar isso, observe a matriz no primeiro parâmetro ([1,11,21,31,41]) e a matriz 'bin' no segundo parâmetro ([0,10,20,30,40,50]) :

  • O número 1 (da primeira matriz) fica entre 0 e 10 (na matriz 'bandejas')
  • O número 11 (da primeira matriz) fica entre 11 e 20 (na matriz 'caixas')
  • O número 21 (da primeira matriz) fica entre 21 e 30 (na matriz 'bandejas'), etc.

Então, eu estou usando o parâmetro 'pesos' para definir o tamanho de cada caixa. Esta é a matriz usada para o parâmetro de pesos: [10,1,40,33,6].

Portanto, o compartimento de 0 a 10 recebe o valor 10, o compartimento de 11 a 20 recebe o valor de 1, o compartimento de 21 a 30 recebe o valor de 40 etc.


3
Eu acho que você tem um mal-entendido básico sobre como a função do histograma funciona. Ele espera dados brutos. Portanto, no seu exemplo, sua matriz de dados deve conter 10 valores entre 0 e 10, 1 valor entre 10 e 20 e assim por diante. Então a função faz a soma E o desenho. O que você está fazendo acima é uma solução alternativa, porque você já possui as somas (que você insere no gráfico usando incorretamente a opção "pesos"). Espero que isso esclareça alguma confusão.
— precisa saber é o seguinte

-1

Para um histograma com valores x inteiros, acabei usando

plt.hist(data, np.arange(min(data)-0.5, max(data)+0.5))
plt.xticks(range(min(data), max(data)))

O deslocamento de 0,5 centraliza os compartimentos nos valores do eixo x. A plt.xtickschamada adiciona uma marca para cada número inteiro.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.