Ich möchte ein ** Histogramm ** mit Python + Pandas + Matplotlib erstellen und die erhaltene ** Normalverteilungskurve ** überlagern, vorausgesetzt, die Population folgt einer Normalverteilung.
Zusätzlich ** Normalitätsprüfung ** durch Shapiro-Wilk-Test **, Intervallschätzung für Populationsmittel ** unter Annahme einer Normalverteilung ** (95% -Konfidenzintervall) Ich werde es auch tun).
Hier möchte ich als Beispiel ein Histogramm für das Testergebnis (für 100 Personen) aus 100 Punkten erstellen.
■ Durchschnitt: 76,1 Punkte, Standardabweichung: 10,3 Punkte --p = 0,77 (p> = 0,05) und man kann sagen, dass die Bevölkerung Normalität hat --95% Konfidenzintervall CI des Populationsmittelwerts CI = [74.09, 78.19]
Wir haben die Ausführung und den Betrieb mit Google Colab (Python 3.6.9) bestätigt. Es ist fast das gleiche wie Jupyter Notebook.
!pip list
matplotlib 3.1.2
numpy 1.17.4
pandas 0.25.3
scipy 1.3.3
Stellen Sie Japanisch im Ausgabediagramm von matplotlib zur Verfügung.
!pip install japanize-matplotlib
import japanize_matplotlib
Mit dem oben genannten wird japanize-matplotlib-1.0.5
installiert und importiert, und selbst wenn Sie Japanisch für Etiketten usw. verwenden, werden die Zeichen nicht verstümmelt (Tofu).
python
%reset -f
import numpy as np
import pandas as pd
import scipy.stats as st
import math
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import matplotlib.transforms as ts
#Generieren Sie Dummy-Daten von Testergebnissen (normale Zufallszahlen (Ganzzahl) im Bereich von 0 bis 100).
def getTestData(mu,sig,n) : #Mittelwert mu, Standardabweichung sig, Anzahl normaler Zufallszahlen n
f = lambda x: min(100,max(0,round( np.random.normal(mu,sig),0)))
return (np.frompyfunc(f, 1, 1)(np.zeros(n))).astype(np.float)
df = pd.DataFrame( {'p1':getTestData(75,8,40)} )
#Diagrammzeichnungsparameter
target = 'p1' #Zu zeichnende Spalten im Datenrahmen
x_min, x_max = 40, 100 #Bewertungsbereich für die Darstellung (untere und obere Grenze)
j = 5 #Schrittweite der Y-Achse (Frequenz)
k = 5 #Abschnittsbreite
bins = 12 #Anzahl der Abschnitte(x_max-x_min)/k (100-40)/5->12
#Grafikzeichnungsprozess von hier
plt.figure(dpi=96)
plt.xlim(x_min,x_max)
d = 0.001
# (1)Statistische Verarbeitung
n = len(df[target]) #Probengröße
mu = df[target].mean() #durchschnittlich
sig = df[target].std(ddof=0) #Standardabweichung: ddof(Freiheitsgrad)=0
print(f'■ Durchschnitt:{mu:.1f}Punkt, Standardabweichung:{sig:.1f}Punkt')
ci1, ci2 = (None, None)
#Normalitätstest (Signifikanzniveau 5)%) Und der Bevölkerungsdurchschnitt von 95%Konfidenzintervall
_, p = st.shapiro(df[target])
if p >= 0.05 :
print(f' - p={p:.2f} ( p>=0.05 )Und man kann sagen, dass die Bevölkerung Normalität hat')
U2 = df[target].var(ddof=1) #Populationsvarianzschätzung (unvoreingenommene Varianz)
DF = n-1 #Freiheitsgrad
SE = math.sqrt(U2/n) #Standart Fehler
ci1,ci2 = st.t.interval( alpha=0.95, loc=mu, scale=SE, df=DF )
print(f' -Bevölkerungsdurchschnitt 95%Konfidenzintervall CI= [{ci1:.2f} , {ci2:.2f}]')
else:
print(f' ※ p={p:.2f} ( p<0.05 )Und die Bevölkerung kann nicht als normal bezeichnet werden')
# (2)Zeichnen eines Histogramms
hist_data = plt.hist(df[target], bins=bins, color='tab:cyan', range=(x_min, x_max), rwidth=0.9)
plt.gca().set_xticks(np.arange(x_min,x_max-k+d, k))
# (3)Ungefähre Kurve unter Annahme einer Normalverteilung
sig = df[target].std(ddof=1) #Unvoreingenommene Standardabweichung: ddof(Freiheitsgrad)=1
nx = np.linspace(x_min, x_max+d, 150) #150 Abteilungen
ny = st.norm.pdf(nx,mu,sig) * k * len(df[target])
plt.plot( nx , ny, color='tab:blue', linewidth=1.5, linestyle='--')
# (4)X-Achsen-Skalierungs- / Beschriftungseinstellung
plt.xlabel('Testergebnisklassifizierung',fontsize=12)
plt.gca().set_xticks(np.arange(x_min,x_max+d, k))
# (5)Skalierungs- / Beschriftungseinstellung der Y-Achse
y_max = max(hist_data[0].max(), st.norm.pdf(mu,mu,sig) * k * len(df[target]))
y_max = int(((y_max//j)+1)*j) #Das kleinste Vielfache von j, das größer als die maximale Frequenz ist
plt.ylim(0,y_max)
plt.gca().set_yticks( range(0,y_max+1,j) )
plt.ylabel('Anzahl der Personen',fontsize=12)
# (6)Textausgabe der Durchschnittspunktzahl und der Standardabweichung
tx = 0.03 #Zur Einstellung der Zeichenausgabeposition
ty = 0.91 #Zur Einstellung der Zeichenausgabeposition
tt = 0.08 #Zur Einstellung der Zeichenausgabeposition
tp = dict( horizontalalignment='left',verticalalignment='bottom',
transform=plt.gca().transAxes, fontsize=11 )
plt.text( tx, ty, f'Durchschnittliche Punktzahl{mu:.2f}', **tp)
plt.text( tx, ty-tt, f'Standardabweichung{sig:.2f}', **tp)
plt.vlines( mu, 0, y_max, color='black', linewidth=1 )
Im Fall eines Histogramms kann es schwierig sein zu sagen, ob der Wert, der die Grenze der Teilung darstellt, in der linken oder rechten Frequenz gezählt wird. Unten finden Sie eine einfachere Version davon.
python
%reset -f
import numpy as np
import pandas as pd
import scipy.stats as st
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import matplotlib.transforms as ts
import math
#Test-Dummy-Daten generieren (0-100)
def getTestData(mu,sig,n) : #Mittelwert mu, Standardabweichung sig, Anzahl normaler Zufallszahlen n
f = lambda x: min(100,max(0,round( np.random.normal(mu,sig),0)))
return (np.frompyfunc(f, 1, 1)(np.zeros(n))).astype(np.float)
df = pd.DataFrame( {'p1':dm} )
#Diagrammzeichnungsparameter
target = 'p1' #Spalten, die im Datenrahmen gezeichnet werden sollen
x_min, x_max = 40, 100 #Bewertungsbereich für die Darstellung (untere und obere Grenze)
j = 5 #Schrittweite der Y-Achse (Frequenz)
k = 5 #Abschnittsbreite
bins = 12 #Anzahl der Abschnitte(x_max-x_min)/k (100-40)/5->12
#Grafikzeichnungsprozess von hier
plt.figure(dpi=96)
plt.xlim(x_min-k/2,x_max-k/2)
d = 0.001
# (1)Statistische Verarbeitung
n = len(df[target]) #Probengröße
mu = df[target].mean() #durchschnittlich
sig = df[target].std(ddof=0) #Standardabweichung: ddof(Freiheitsgrad)=0
print(f'■ Durchschnitt:{mu:.1f}Punkt, Standardabweichung:{sig:.1f}Punkt')
ci1, ci2 = (None, None)
#Normalitätstest (Signifikanzniveau 5)%) Und der Bevölkerungsdurchschnitt von 95%Konfidenzintervall
_, p = st.shapiro(df[target])
if p >= 0.05 :
print(f' - p={p:.2f} ( p>=0.05 )Und man kann sagen, dass die Bevölkerung Normalität hat')
U2 = df[target].var(ddof=1) #Populationsvarianzschätzung (unvoreingenommene Varianz)
DF = n-1 #Freiheitsgrad
SE = math.sqrt(U2/n) #Standart Fehler
ci1,ci2 = st.t.interval( alpha=0.95, loc=mu, scale=SE, df=DF )
print(f' -Bevölkerungsdurchschnitt 95%Konfidenzintervall CI= [{ci1:.2f} , {ci2:.2f}]')
else:
print(f' ※ p={p:.2f} ( p<0.05 )Und die Bevölkerung kann nicht als normal bezeichnet werden')
# (2)Zeichnen eines Histogramms
hist_data = plt.hist(df[target], bins=bins, color='tab:cyan', range=(x_min, x_max), rwidth=0.9, align='left')
plt.gca().set_xticks(np.arange(x_min,x_max-k+d, k))
# (3)Ungefähre Kurve unter Annahme einer Normalverteilung
sig = df[target].std(ddof=1) #Unvoreingenommene Standardabweichung: ddof(Freiheitsgrad)=1
nx = np.linspace(x_min, x_max+d, 150) #150 Abteilungen
ny = st.norm.pdf(nx,mu,sig) * k * len(df[target])
plt.plot( nx - k/2 , ny, color='tab:blue', linewidth=1.5, linestyle='--')
# (4)X-Achsen-Skalierungs- / Beschriftungseinstellung
plt.xticks(rotation=90)
plt.xlabel('Testergebnisklassifizierung',fontsize=12)
tmp = list([ f'${i} \\leq x < {i+k}$' for i in range(x_min,x_max-k+1, k) ])
tmp[-1] = f'${x_max-k} \\leq x \\leq {x_max}$'
plt.gca().set_xticklabels( tmp )
# (5)Skalierungs- / Beschriftungseinstellung der Y-Achse
y_max = max(hist_data[0].max(), st.norm.pdf(mu,mu,sig) * k * len(df[target]))
y_max = int(((y_max//j)+1)*j) #Das kleinste Vielfache von j, das größer als die maximale Frequenz ist
plt.ylim(0,y_max)
plt.gca().set_yticks( range(0,y_max+1,j) )
plt.ylabel('Anzahl der Personen',fontsize=12)
Recommended Posts