[PYTHON] Je veux créer un histogramme et superposer la courbe de distribution normale dessus. édition matplotlib

Aperçu

Je voudrais créer un ** histogramme ** avec Python + pandas + matplotlib et superposer la ** courbe de distribution normale ** obtenue en supposant que la population suit une distribution normale.

En outre, ** contrôle de normalité ** par test de Shapiro-Wilk **, estimation d'intervalle pour la moyenne de la population ** en supposant une distribution normale ** (intervalle de confiance à 95%) Je ferai aussi).

Ici, à titre d'exemple, je voudrais créer un histogramme pour le score du test (pour 100 personnes) sur 100 points.

fig1.png

■ Moyenne: 76,1 points, écart-type: 10,3 points --p = 0,77 (p> = 0,05) et on peut dire que la population a une normalité Intervalle de confiance> --95% IC de l'IC moyen de la population = [74,09, 78,19]

Entrées connexes

Environnement d'exécution

Nous avons confirmé l'exécution et le fonctionnement avec Google Colab (Python 3.6.9). C'est presque le même que Jupyter Notebook.

!pip list 
matplotlib               3.1.2
numpy                    1.17.4
pandas                   0.25.3
scipy                    1.3.3

Préparation à l'utilisation du japonais avec matplotlib

Rendre le japonais disponible dans le diagramme de sortie de matplotlib.

!pip install japanize-matplotlib
import japanize_matplotlib

Avec ce qui précède, japanize-matplotlib-1.0.5 sera installé et importé, et même si vous utilisez le japonais pour les étiquettes, etc., les caractères ne seront pas déformés (tofu).

code

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 

#Générer des données fictives des résultats de test (nombres aléatoires normaux (entier) compris entre 0 et 100)
def getTestData(mu,sig,n) : #Moyenne mu, écart type sig, nombre de nombres aléatoires normaux 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)} )

#Paramètres de dessin graphique
target = 'p1'           #Colonnes à tracer dans le bloc de données
x_min, x_max = 40, 100  #Plage de score à tracer (limites inférieure et supérieure)
j = 5                   #Taille de pas de l'axe Y (fréquence)
k = 5                   #Largeur de section
bins = 12               #Nombre de sections(x_max-x_min)/k  (100-40)/5->12

#Processus de dessin de graphique à partir d'ici
plt.figure(dpi=96)
plt.xlim(x_min,x_max)
d = 0.001

# (1)Traitement statistique
n   = len(df[target])         #Taille de l'échantillon
mu  = df[target].mean()       #moyenne
sig = df[target].std(ddof=0)  #Écart type: ddof(Degré de liberté)=0
print(f'■ Moyenne:{mu:.1f}Point, écart type:{sig:.1f}point')
ci1, ci2 = (None, None)

#Test de normalité (niveau de signification 5)%) Et la population moyenne de 95%Intervalle de confiance
_, p = st.shapiro(df[target])
if p >= 0.05 :
  print(f'  - p={p:.2f} ( p>=0.05 )Et on peut dire que la population a la normalité')
  U2 = df[target].var(ddof=1)  #Estimation de la variance de la population (variance sans biais)
  DF = n-1                     #Degré de liberté
  SE = math.sqrt(U2/n)         #Erreur standard
  ci1,ci2 = st.t.interval( alpha=0.95, loc=mu, scale=SE, df=DF )
  print(f'  -Population moyenne 95%IC de l'intervalle de confiance= [{ci1:.2f} , {ci2:.2f}]')
else:
  print(f'  ※ p={p:.2f} ( p<0.05 )Et on ne peut pas dire que la population est normale')

# (2)Dessiner un histogramme
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)Courbe approximative en supposant une distribution normale
sig = df[target].std(ddof=1)  #Écart-type impartial: ddof(Degré de liberté)=1
nx = np.linspace(x_min, x_max+d, 150) #150 divisions
ny = st.norm.pdf(nx,mu,sig) * k * len(df[target])
plt.plot( nx , ny, color='tab:blue', linewidth=1.5, linestyle='--')

# (4)Réglage de l'échelle / étiquette de l'axe X
plt.xlabel('Classement des scores de test',fontsize=12)
plt.gca().set_xticks(np.arange(x_min,x_max+d, k))

# (5)Réglage de l'échelle / étiquette de l'axe Y
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) #Le plus petit multiple de j supérieur à la fréquence maximale
plt.ylim(0,y_max)
plt.gca().set_yticks( range(0,y_max+1,j) )
plt.ylabel('Nombre de personnes',fontsize=12)

# (6)Sortie texte du score moyen et de l'écart type
tx = 0.03 #Pour le réglage de la position de sortie des caractères
ty = 0.91 #Pour le réglage de la position de sortie des caractères
tt = 0.08 #Pour le réglage de la position de sortie des caractères
tp = dict( horizontalalignment='left',verticalalignment='bottom',
           transform=plt.gca().transAxes, fontsize=11 )
plt.text( tx, ty, f'Score moyen{mu:.2f}', **tp)
plt.text( tx, ty-tt, f'écart-type{sig:.2f}', **tp)
plt.vlines( mu, 0, y_max, color='black', linewidth=1 )

Code 2

Dans le cas d'un histogramme, il peut être difficile de dire si la valeur qui est la limite de la division est comptée dans la fréquence gauche ou droite. Vous en trouverez ci-dessous une version plus simple.

fig2.png

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

#Générer des données factices de test (0-100)
def getTestData(mu,sig,n) : #Moyenne mu, écart type sig, nombre de nombres aléatoires normaux 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} )

#Paramètres de dessin graphique
target = 'p1'           #Colonnes à tracer dans le bloc de données
x_min, x_max = 40, 100  #Plage de score à tracer (limites inférieure et supérieure)
j = 5                   #Taille de pas de l'axe Y (fréquence)
k = 5                   #Largeur de section
bins = 12               #Nombre de sections(x_max-x_min)/k  (100-40)/5->12

#Processus de dessin de graphique à partir d'ici
plt.figure(dpi=96)
plt.xlim(x_min-k/2,x_max-k/2)
d = 0.001

# (1)Traitement statistique
n   = len(df[target])         #Taille de l'échantillon
mu  = df[target].mean()       #moyenne
sig = df[target].std(ddof=0)  #Écart type: ddof(Degré de liberté)=0
print(f'■ Moyenne:{mu:.1f}Point, écart type:{sig:.1f}point')
ci1, ci2 = (None, None)

#Test de normalité (niveau de signification 5)%) Et la population moyenne de 95%Intervalle de confiance
_, p = st.shapiro(df[target])
if p >= 0.05 :
  print(f'  - p={p:.2f} ( p>=0.05 )Et on peut dire que la population a la normalité')
  U2 = df[target].var(ddof=1)  #Estimation de la variance de la population (variance sans biais)
  DF = n-1                     #Degré de liberté
  SE = math.sqrt(U2/n)         #Erreur standard
  ci1,ci2 = st.t.interval( alpha=0.95, loc=mu, scale=SE, df=DF )
  print(f'  -Population moyenne 95%IC de l'intervalle de confiance= [{ci1:.2f} , {ci2:.2f}]')
else:
  print(f'  ※ p={p:.2f} ( p<0.05 )Et on ne peut pas dire que la population est normale')

# (2)Dessiner un histogramme
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)Courbe approximative en supposant une distribution normale
sig = df[target].std(ddof=1)  #Écart-type impartial: ddof(Degré de liberté)=1
nx = np.linspace(x_min, x_max+d, 150) #150 divisions
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)Réglage de l'échelle / étiquette de l'axe X
plt.xticks(rotation=90)
plt.xlabel('Classement des scores de test',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)Réglage de l'échelle / étiquette de l'axe Y
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) #Le plus petit multiple de j supérieur à la fréquence maximale
plt.ylim(0,y_max)
plt.gca().set_yticks( range(0,y_max+1,j) )
plt.ylabel('Nombre de personnes',fontsize=12)

Recommended Posts

Je veux créer un histogramme et superposer la courbe de distribution normale dessus. édition matplotlib
Je veux créer un fichier pip et le refléter dans le menu fixe
J'ai créé un script POST pour créer un problème sur Github et l'enregistrer dans le projet
Je souhaite créer manuellement une légende avec matplotlib
Je veux créer un Dockerfile pour le moment.
Je veux trouver l'intersection d'une courbe de Bézier et d'une ligne droite (méthode de découpage de Bézier)
Je souhaite produire une carte thermique magnifiquement personnalisée de la matrice de corrélation. édition matplotlib
Je souhaite enregistrer l'heure d'exécution et conserver un journal.
Je veux faire de matplotlib un thème sombre
Je souhaite créer facilement un modèle de bruit
Je souhaite créer un type d'implémentation pouvant être branché
Je veux déposer un fichier sur tkinter et obtenir son chemin [Tkinter DnD2]
Je veux créer un lecteur de musique et enregistrer de la musique en même temps
Je veux écrire un élément dans un fichier avec numpy et le vérifier.
Je souhaite convertir du texte horizontal en texte vertical et le publier sur Twitter, etc.
Je veux trouver un package populaire sur PyPi
C'était une vie que je voulais faire de l'OCR sur AWS Lambda pour localiser les personnages.
Je souhaite prendre une capture d'écran du site sur Docker en utilisant n'importe quelle police
Étapes pour calculer la probabilité d'une distribution normale
Je veux remplacer les variables dans le fichier de modèle python et le produire en masse dans un autre fichier
Je souhaite créer une base de données de déjeuners [EP1] Django pour la première fois
[Python] Comment créer un histogramme bidimensionnel avec Matplotlib
Il est difficile d'installer un écran vert, je n'ai donc découpé que le visage et l'ai superposé sur l'image de fond
Je veux découper uniquement le visage d'une image de personne avec Python et l'enregistrer ~ Détection de visage et rognage avec face_recognition ~
Avec matplotlib, l'axe vertical sur le côté gauche de l'histogramme est la fréquence, et l'axe vertical sur le côté droit est la fréquence relative (peut-être une mauvaise manière)
J'ai créé un outil qui facilite un peu la création et l'installation d'une clé publique.
Quand j'ai essayé d'installer PIL et matplotlib dans un environnement virtualenv, j'en étais accro.
Je veux absorber la différence entre l'instruction for sur la matrice Python + numpy et l'instruction Julia for
Je souhaite créer une source sonore de karaoké en séparant les instruments et les voix en utilisant Python
Je veux connaître la nature de Python et pip
Je souhaite mapper le code EDINET et le numéro de valeur
Je veux connaître la légende du monde des technologies informatiques
Lors de la génération d'un grand nombre de graphiques avec matplotlib, je ne souhaite pas afficher le graphique à l'écran (environnement jupyter)
Je veux obtenir des informations de fstab à la destination de la connexion ssh et exécuter la commande
Je veux clarifier la question de la méthode "__init__" et de l'argument "self" de la classe Python.
Je souhaite extraire les informations d'étiquette (titre et artiste) d'un fichier de musique (flac, wav).
Est-il facile de synthétiser un médicament sur le marché?
Qiskit: Je veux créer un circuit qui crée des états arbitraires! !!
J'ai essayé d'enregistrer une station sur la plateforme IoT "Rimotte"
Gratter et manger des bûches - je veux trouver un bon restaurant! ~ (Travail)
J'ai essayé de créer des taureaux et des vaches avec un programme shell
Je souhaite créer un service d'apprentissage automatique sans programmation! API Web
J'ai exécuté GhostScript avec python, divisé le PDF en pages et l'ai converti en image JPEG.
Je souhaite recevoir le fichier de configuration et vérifier si le fichier JSON généré par jinja2 est un JSON valide
J'ai essayé de pousser les documents Sphinx vers BitBucket et de les refléter automatiquement sur le serveur Web
Je souhaite résoudre le problème de fuite de mémoire lors de la sortie d'un grand nombre d'images avec Matplotlib
Mettez à jour les données en les téléchargeant sur s3 d'aws avec une commande, et supprimez les données utilisées (en chemin)
Je veux changer la couleur en cliquant sur le point de dispersion dans matplotlib
Je veux tweeter Twitter avec Python, mais j'y suis accro
J'ai essayé de visualiser la tranche d'âge et la distribution des taux d'Atcoder
Je souhaite séparer le traitement entre le temps de test et l'environnement de production
Je ne veux pas l'admettre ... Représentation dynamique du système de Neural Network
J'ai fait une minuterie de cuisine à afficher sur la barre d'état!
[Python] Créez un linebot pour écrire le nom et l'âge sur l'image
Je souhaite trier une liste dans l'ordre des autres listes
[Mémo personnel] Obtenez des données sur le Web et faites-en un DataFrame
Touches de karaoké assorties ~ J'ai essayé de le mettre sur Laravel ~ <en route>