Python'da Matplotlib kullanarak bir veri listesi ile bir histogram nasıl çizilir?


106

matplotlib.hist()Fonksiyonu kullanarak bir histogram çizmeye çalışıyorum ama nasıl yapacağımı bilmiyorum.

Bir listem var

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]

ve bir isim listesi (dizeler).

Olasılığı her çubuğun y değeri ve x değerleri olarak nasıl adlandırabilirim?

Yanıtlar:


180

Bir histogram istiyorsanız, x değerlerine herhangi bir 'ad' eklemenize gerek yoktur, çünkü x ekseninde veri bölmeleriniz olacaktır:

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

görüntü açıklamasını buraya girin

Histogramınızı PDFçizgi, başlıklar ve açıklamalarla biraz daha meraklı hale getirebilirsiniz :

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

görüntü açıklamasını buraya girin

Bununla birlikte, OP'de olduğu gibi sınırlı sayıda veri noktanız varsa, bir çubuk grafiği verilerinizi temsil etmek için daha mantıklı olacaktır (o zaman x eksenine etiketler ekleyebilirsiniz):

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

görüntü açıklamasını buraya girin


4
Unutmayın, python'daki satırların sonunda noktalı virgül yok!
Toad22222

12
@ Toad22222 Bu, Ipython dizüstü bilgisayar hücresinden bir alıntıdır. Noktalı virgül olmadan çalıştırmayı deneyin ve farkı görün. SO'da yayınladığım tüm kod parçacıkları bilgisayarımda mükemmel çalışıyor.
Sergey Bushmanov

3
Sergey tarafından kullanılan noktalı virgülü merak ediyorsanız , Jupyter not defterleri (eski adıyla IPython not defterleri) hücrelerinde arsa nesnesi hakkındaki metni bastırmak için çizim yaparken noktalı virgülün nasıl kullanıldığını görmek için buraya ve # 16'ya bakın .
Wayne

20

Matplotlib'i henüz kurmadıysanız, sadece komutu deneyin.

> pip install matplotlib

Kitaplık içe aktarma

import matplotlib.pyplot as plot

Histogram verileri:

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

Histogramı görüntüle

plot.show()

Ve çıktı şöyle:

görüntü açıklamasını buraya girin


3
Plot.axis ([50, 110, 0, 0.06]) 'satırı örnek için kullanışsızdır. Ayrıca, gösterilecek arsa alanını sabit kodladığından, verileriniz tamamen içine sığmıyorsa, neden doğru şekilde gösterilmediği konusunda kafanız karışabilir.
typhon04

10

Soru matplotlib.hist(), fonksiyon kullanarak bir histogramı çizmeyi gerektiriyor gibi görünse de, sorunun ikinci bölümünün verilen olasılıkları çubukların y-değerleri ve verilen isimler (dizeler) x değerleri.

Grafiği çizmek için verilen olasılıklara karşılık gelen örnek bir isim listesi varsayıyorum. Verilen problem için basit bir çubuk grafiği burada amaca hizmet eder. Aşağıdaki kod kullanılabilir:

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

5

Bu eski bir sorudur, ancak önceki cevapların hiçbiri gerçek meseleye, yani sorunun sorunun kendisinde olduğu gerçeğine değinmemiştir.

Birincisi, olasılıklar önceden hesaplanmışsa, yani toplanan histogram verileri normalleştirilmiş bir şekilde mevcutsa, olasılıklar 1'e kadar eklenmelidir. Açıkçası yok ve bu, terminoloji veya verilerle burada bir şeylerin yanlış olduğu anlamına gelir. ya da sorunun sorulduğu şekilde.

İkincisi, etiketlerin (aralıkların değil) sağlanmış olması, normal olarak olasılıkların kategorik yanıt değişkenine ait olduğu anlamına gelir ve histogramı çizmek için bir çubuk grafiğinin kullanılması en iyisidir (veya pyplot'un geçmiş yönteminin bir miktar hacklenmesi). Shayan Shafiq'in cevabı kodu sağlıyor.

Bununla birlikte, sorun 1'e bakın, bu olasılıklar doğru değildir ve bu durumda çubuk grafiği kullanmak yanlış olacaktır çünkü bir sebepten dolayı tek değişkenli dağılımın hikayesini anlatmaz (belki de sınıflar örtüşüyor ve gözlemler birden fazla sayılıyor) kez?) ve böyle bir çizim bu durumda histogram olarak adlandırılmamalıdır.

Histogram, tanımı gereği, tek değişkenli değişken dağılımının grafik bir temsilidir (bkz. Https://www.itl.nist.gov/div898/handbook/eda/section3/histogra.htm , https://en.wikipedia.org/wiki / Histogram) ve ilgilenilen değişkenin seçilen sınıflarında gözlemlerin sayımlarını veya sıklıklarını temsil eden boyutlarda çubuklar çizilerek oluşturulur. Değişken sürekli bir ölçekte ölçülürse, bu sınıflar bölmelerdir (aralıklar). Histogram oluşturma prosedürünün önemli bir parçası, kategorik bir değişken için yanıt kategorilerinin nasıl gruplandırılacağına (veya gruplandırılmadan tutulacağına) veya olası değerlerin alan adının aralıklara nasıl bölüneceğine (ikili sınırları nereye koyacağınıza) karar vermektir. tip değişken. Tüm gözlemler temsil edilmeli ve her biri olay örgüsünde yalnızca bir kez olmalıdır. Bu, çubuk boyutlarının toplamının toplam gözlem sayısına (veya daha az yaygın bir yaklaşım olan değişken genişlikler durumunda alanlarına) eşit olması gerektiği anlamına gelir. Veya histogram normalleştirilmişse, tüm olasılıkların toplamı 1 olmalıdır.

Verinin kendisi yanıt olarak "olasılıklar" listesiyse, yani gözlemler her çalışma nesnesi için olasılık değerleriyse (bir şeyin) o zaman en iyi yanıt, plt.hist(probability)belki binning seçeneğidir ve zaten mevcut olan x etiketlerinin kullanımı şüpheli.

O zaman çubuk grafiği, histogram olarak kullanılmamalı, basitçe

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

sonuçlarla

görüntü açıklamasını buraya girin

Böyle bir durumda matplotlib varsayılan olarak aşağıdaki histogram değerleriyle gelir

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

sonuç bir dizi dizisidir, ilk dizi gözlem sayılarını içerir, yani arsanın y eksenine göre gösterilecekler (toplamlar 13, toplam gözlem sayısı) ve ikinci dizi x için aralık sınırlarıdır. eksen.

Eşit aralıklı oldukları kontrol edilebilir,

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

görüntü açıklamasını buraya girin

Veya örneğin 3 bölme için (benim kararım 13 gözlem gerektiriyor) bu histogramı elde edebilirsiniz

plt.hist(probability, bins=3)

görüntü açıklamasını buraya girin

arsa verileri "parmaklıkların arkasında"

görüntü açıklamasını buraya girin

Sorunun yazarının, değerlerin "olasılık" listesinin anlamının ne olduğunu açıklığa kavuşturması gerekir - "olasılık", yanıt değişkeninin yalnızca bir adıdır (öyleyse neden histogram için hazır x etiketleri var, bu anlam ifade etmiyor) ) veya listedeki değerler verilerden hesaplanan olasılıklardır (bu durumda toplamlarının 1'e kadar çıkmaması hiçbir anlam ifade etmez).


4

Bu, bunu yapmanın çok kapsamlı bir yoludur, ancak bin değerlerini zaten bildiğiniz ancak kaynak verilere sahip olmadığınız bir histogram np.random.randintoluşturmak istiyorsanız , her birinin aralığı içinde doğru sayıda değer üretmek için işlevi kullanabilirsiniz. hist işlevinin grafiğe dökülmesi için bin, örneğin:

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

etiketlere gelince, şunun gibi bir şey elde etmek için x işaretini kutularla hizalayabilirsiniz:

#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.. ])
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.