Comment tracer un histogramme en utilisant Matplotlib en Python avec une liste de données?

100

J'essaie de tracer un histogramme en utilisant la matplotlib.hist()fonction mais je ne sais pas comment le faire.

J'ai une liste

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]

et une liste de noms (chaînes).

Comment définir la probabilité comme valeur y de chaque barre et les noms comme valeurs x?

DataVizGuys
la source

Réponses:

168

Si vous voulez un histogramme, vous n'avez pas besoin d'attacher de `` noms '' aux valeurs x, car sur l'axe des x vous auriez des bacs de données:

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

entrez la description de l'image ici

Vous pouvez rendre votre histogramme un peu plus élégant avec des PDFlignes, des titres et une légende:

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

entrez la description de l'image ici

Cependant, si vous avez un nombre limité de points de données, comme dans OP, un graphique à barres aurait plus de sens pour représenter vos données (vous pouvez alors attacher des étiquettes à l'axe des x):

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

entrez la description de l'image ici

Sergey Bushmanov
la source
4
N'oubliez pas, pas de point-virgule à la fin des lignes en python!
Toad22222
10
@ Toad22222 Ceci est un extrait de la cellule du notebook Ipython. Essayez de l'exécuter sans point-virgule et voyez la différence. Tous les extraits de code que je poste sur SO fonctionnent parfaitement sur mon ordinateur.
Sergey Bushmanov
2
Si vous vous interrogez sur le point-virgule utilisé par Sergey, voir ici et # 16 ici pour savoir comment le point-virgule est utilisé dans les cellules des blocs-notes Jupyter (anciennement des blocs-notes IPython) lors du traçage pour supprimer le texte sur l'objet de tracé.
Wayne
19

Si vous n'avez pas encore installé matplotlib, essayez simplement la commande.

> pip install matplotlib

Import de bibliothèque

import matplotlib.pyplot as plot

Les données de l'histogramme:

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

Afficher l'histogramme

plot.show()

Et la sortie est comme:

entrez la description de l'image ici

Niraj
la source
2
La ligne plot.axis ([50, 110, 0, 0.06]) 'est inutile pour l'exemple. En outre, comme il code en dur la zone de l'intrigue à afficher, si vos données ne rentrent pas entièrement à l'intérieur, vous pouvez être confus pourquoi cela ne s'affiche pas correctement.
typhon04
10

Bien que la question semble exigeante pour tracer un histogramme à l'aide d'une matplotlib.hist()fonction, elle ne peut sans doute pas être effectuée en utilisant la même chose que la dernière partie de la question exige d'utiliser les probabilités données comme valeurs y des barres et des noms donnés (chaînes) comme valeurs x.

Je suppose un exemple de liste de noms correspondant à des probabilités données pour dessiner l'intrigue. Un simple diagramme à barres sert ici le problème donné. Le code suivant peut être utilisé:

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
la source
5

C'est une vieille question mais aucune des réponses précédentes n'a abordé le vrai problème, c'est-à-dire le fait que le problème vient de la question elle-même.

Premièrement, si les probabilités ont déjà été calculées, c'est-à-dire que les données agrégées de l'histogramme sont disponibles de manière normalisée, les probabilités devraient s'additionner à 1. Ce n'est évidemment pas le cas et cela signifie que quelque chose ne va pas ici, soit avec la terminologie, soit avec les données ou dans la manière dont la question est posée.

Deuxièmement, le fait que les étiquettes soient fournies (et non des intervalles) signifierait normalement que les probabilités sont des variables de réponse catégorielles - et l'utilisation d'un diagramme à barres pour tracer l'histogramme est préférable (ou un piratage de la méthode hist du pyplot), La réponse de Shayan Shafiq fournit le code.

Cependant, voir le problème 1, ces probabilités ne sont pas correctes et utiliser un diagramme à barres dans ce cas comme «histogramme» serait faux car il ne raconte pas l'histoire de la distribution univariée, pour une raison quelconque (peut-être que les classes se chevauchent et que les observations sont comptées plusieurs fois?) et un tel tracé ne doit pas être appelé un histogramme dans ce cas.

L'histogramme est par définition une représentation graphique de la distribution d'une variable univariée (voir https://www.itl.nist.gov/div898/handbook/eda/section3/histogra.htm , https://en.wikipedia.org/wiki / Histogramme) et est créé en dessinant des barres de tailles représentant des nombres ou des fréquences d'observations dans des classes sélectionnées de la variable d'intérêt. Si la variable est mesurée sur une échelle continue, ces classes sont des cases (intervalles). Une partie importante de la procédure de création d'histogramme consiste à choisir comment regrouper (ou conserver sans regrouper) les catégories de réponses pour une variable catégorielle, ou comment diviser le domaine des valeurs possibles en intervalles (où placer les limites de la case) pour variable de type. Toutes les observations doivent être représentées et chacune une seule fois dans le graphique. Cela signifie que la somme des tailles des barres doit être égale au nombre total d'observations (ou à leurs surfaces dans le cas des largeurs variables, ce qui est une approche moins courante). Ou, si l'histogramme est normalisé, toutes les probabilités doivent totaliser 1.

Si les données elles-mêmes sont une liste de «probabilités» comme réponse, c'est-à-dire que les observations sont des valeurs de probabilité (de quelque chose) pour chaque objet d'étude, alors la meilleure réponse est simplement plt.hist(probability)avec l'option peut-être de regroupement, et l'utilisation d'étiquettes x déjà disponibles est méfiant.

Ensuite, le graphique à barres ne doit pas être utilisé comme histogramme mais plutôt simplement

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

avec les résultats

entrez la description de l'image ici

matplotlib dans ce cas arrive par défaut avec les valeurs d'histogramme suivantes

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

le résultat est un tuple de tableaux, le premier tableau contient les décomptes d'observations, c'est-à-dire ce qui sera affiché par rapport à l'axe y du tracé (ils totalisent 13, le nombre total d'observations) et le deuxième tableau est les limites d'intervalle pour x -axe.

On peut vérifier qu'ils sont également espacés,

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

entrez la description de l'image ici

Ou, par exemple pour 3 bacs (mon jugement appelle 13 observations) on obtiendrait cet histogramme

plt.hist(probability, bins=3)

entrez la description de l'image ici

avec les données de tracé "derrière les barreaux" étant

entrez la description de l'image ici

L'auteur de la question doit clarifier la signification de la liste de valeurs «probabilité» - la «probabilité» est-elle juste un nom de la variable de réponse (alors pourquoi y a-t-il des étiquettes x prêtes pour l'histogramme, cela n'a aucun sens ), ou les valeurs de liste sont-elles les probabilités calculées à partir des données (alors le fait qu'elles ne totalisent pas 1 n'a aucun sens).

predmod
la source
4

C'est une façon très ronde de le faire, mais si vous souhaitez créer un histogramme dans lequel vous connaissez déjà les valeurs de casier mais que vous n'avez pas les données source, vous pouvez utiliser la np.random.randintfonction pour générer le nombre correct de valeurs dans la plage de chaque bin pour la fonction hist à représenter graphiquement, par exemple:

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

en ce qui concerne les étiquettes, vous pouvez aligner x graduations avec des bacs pour obtenir quelque chose comme ceci:

#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
la source