web-dev-qa-db-fra.com

pylab.hist (data, normed = 1). La normalisation semble ne pas fonctionner correctement

J'essaie de créer un histogramme avec l'argument normed = 1

Par exemple:

import pylab

data = ([1,1,2,3,3,3,3,3,4,5.1])    
pylab.hist(data, normed=1)
pylab.show()

Je m'attendais à ce que la somme des bacs soit de 1. Mais au lieu de cela, l'un des bacs est plus grand que 1. Qu'est-ce que cette normalisation a fait? Et comment créer un histogramme avec une telle normalisation que l'intégrale de l'histogramme serait égale à 1?

enter image description here

36
smirnoffs

Voir mon autre article pour savoir comment faire la somme de tous les bacs d'un histogramme égal à un: https://stackoverflow.com/a/16399202/1542814

Copier coller:

weights = np.ones_like(myarray)/float(len(myarray))
plt.hist(myarray, weights=weights)

où myarray contient vos données

43
Carsten König

Selon documentationnormed: Si la valeur est True, le résultat est la valeur de la fonction de densité de probabilité au niveau de la corbeille, normalisée de telle sorte que l'intégrale sur la plage soit 1. Notez que la somme des valeurs de l'histogramme ne sera pas égal à 1 sauf si des cases de largeur unitaire sont choisies; ce n'est pas une fonction de masse de probabilité. Cela vient de numpy doc, mais devrait être identique pour pylab.

In []: data= array([1,1,2,3,3,3,3,3,4,5.1])
In []: counts, bins= histogram(data, normed= True)
In []: counts
Out[]: array([ 0.488,  0.,  0.244,  0.,  1.22,  0.,  0.,  0.244,  0.,  0.244])
In []: sum(counts* diff(bins))
Out[]: 0.99999999999999989

Donc, la normalisation est simplement faite selon la documentation comme:

In []: counts, bins= histogram(data, normed= False)
In []: counts
Out[]: array([2, 0, 1, 0, 5, 0, 0, 1, 0, 1])
In []: counts_n= counts/ sum(counts* diff(bins))
In []: counts_n
Out[]: array([ 0.488,  0.,  0.244,  0.,  1.22 ,  0.,  0.,  0.244,  0.,  0.244])
23
eat

Je pense que vous confondez les hauteurs de bac avec le contenu de bac. Vous devez ajouter le contenu de chaque bac, à savoir hauteur * largeur pour tous les bacs. Cela devrait = 1.

7
juanchopanza

J'ai eu le même problème et, tout en le résolvant, un autre problème est apparu: comment tracer les fréquences bin normalisées sous forme de pourcentages avec des graduations sur les valeurs arrondi. Je le poste ici au cas où il serait utile à quiconque. Dans mon exemple, j'ai choisi 10% (0,1) comme valeur maximale pour l'axe des ordonnées et 10 étapes (une de 0% à 1%, une de 1% à 2%, etc.). L'astuce consiste à définir les graduations sur les comptes data (qui sont la liste de sortie n du plt.hist) qui seront ensuite transformés en pourcentages à l'aide de la classe FuncFormatter. Voici ce que j'ai fait:

import matplotlib.pyplot as plt
from matplotlib.ticker import FuncFormatter

fig, ax = plt.subplots()

# The required parameters
num_steps = 10
max_percentage = 0.1
num_bins = 40

# Calculating the maximum value on the y axis and the yticks
max_val = max_percentage * len(data)
step_size = max_val / num_steps
yticks = [ x * step_size for x in range(0, num_steps+1) ]
ax.set_yticks( yticks )
plt.ylim(0, max_val)

# Running the histogram method
n, bins, patches = plt.hist(data, num_bins)

# To plot correct percentages in the y axis     
to_percentage = lambda y, pos: str(round( ( y / float(len(data)) ) * 100.0, 2)) + '%'
plt.gca().yaxis.set_major_formatter(FuncFormatter(to_percentage))

plt.show()

Parcelles

Avant la normalisation: l’unité de l’axe des y est le nombre d’échantillons compris entre les intervalles de la corbeille de l’axe des x: Before normalisation: the y axis unit is number of samples within the bin intervals in the x axis

Après normalisation: l’unité de l’axe des y est la fréquence des valeurs de chutes en pourcentage sur tous les échantillons After normalisation: the y axis unit is frequency of the bin values as a percentage over all the samples

5
Orestis Tsinalis

Qu'est-ce que cette normalisation a fait?

Pour normaliser une séquence, vous devez prendre en compte la taille du fichier . Selon documentation , le nombre de fichiers par défaut est 10. Par conséquent, la taille du fichier est (data.max() - data.min() )/10, soit 0,41 . Si normed=1, la hauteur de la barre est telle que la somme, multipliée par 0,4, donne 1. C’est ce qui se produit lors de l’intégration.

Et comment créer un histogramme avec une telle normalisation que l'intégrale de l'histogramme serait égale à 1?

Je pense que vous voulez que la somme de l'histogramme, et non de son intégrale, soit égale à 1. Dans ce cas, le moyen le plus rapide semble:

h = plt.hist(data)
norm = sum(data)
h2 = [i/norm for i in h[0]]
plt.bar(h[1],h2)
5
altroware

Il existe également un analogue dans numpy - numpy.historgram: http://docs.scipy.org/doc/numpy/reference/generated/numpy.histogram.html L’un des paramètres est "densité", Si Si vous définissez density=True, la sortie sera normalisée.

normed: bool, optionnel Ce mot-clé est déconseillé dans Numpy 1.6 en raison d'un comportement source de confusion/buggy. Il sera supprimé dans Numpy 2.0. Utilisez le mot-clé densité à la place. Si False, le résultat contiendra le nombre d'échantillons dans chaque groupe. Si la valeur est True, le résultat correspond à la valeur de la fonction de densité de probabilité au niveau de la corbeille, normalisée de telle sorte que l'intégrale sur la plage soit égale à 1. Notez que ce dernier comportement est connu pour être problématique avec des largeurs de corbeille inégales; utilisez plutôt la densité.

densité: bool, facultatif Si False, le résultat contiendra le nombre d'échantillons dans chaque groupe. Si la valeur est True, le résultat est la valeur de la fonction de densité de probabilité au niveau de la corbeille, normalisée de telle sorte que l'intégrale sur l'intervalle soit égale à 1. Notez que la somme des valeurs de l'histogramme ne sera pas égale à 1 si les plages de largeur unitaire sont choisies; ce n'est pas une fonction de masse de probabilité. Remplace le mot-clé normé, le cas échéant.

2
Alexandra Shchukina

Vos attentes sont fausses

La somme des bacs hauteur fois sa largeur égale à un. Ou, comme vous l'avez dit correctement, le intégrale doit être un, pas la fonction vous intégrez environ.

C'est comme ceci: probabilité (comme dans "la probabilité que la personne ait entre 20 et 40 ans soit ...%") est l'intégrale ("de 20 à 40 ans") sur la densité de probabilité. La hauteur des bacs indique la densité de probabilité, tandis que la largeur multipliée par la hauteur indique la probabilité (vous intégrez la fonction supposée constante, hauteur de bac, du début à la fin d'un bac) pour qu'un certain point se trouve dans ce bac. La hauteur elle-même est la densité et pas une probabilité. Il s'agit d'une probabilité par largeur qui peut être supérieure à une bien sûr.

Exemple simple: imaginez une fonction de densité de probabilité de 0 à 1 ayant la valeur 0 de 0 à 0,9. Quelle pourrait être la fonction entre 0,9 et 1? Si vous intégrez dessus, essayez-le. Il sera plus élevé que 1.

Btw: à partir d'une approximation approximative, la somme de la hauteur fois la largeur de votre historique semble donner environ 1, n'est-ce pas?

0
Mayou36