web-dev-qa-db-fra.com

Comment normaliser un histogramme dans MATLAB?

Comment normaliser un histogramme tel que l'aire sous la fonction de densité de probabilité soit égale à 1?

44
cMinor

Ma réponse à cette question est la même que dans une réponse à votre question précédente . Pour une fonction de densité de probabilité, l'intégrale sur tout l'espace est 1 . La division par la somme et non vous donnera la densité correcte. Pour obtenir la bonne densité, vous devez diviser par la superficie. Pour illustrer mon propos, essayez l'exemple suivant.

[f, x] = hist(randn(10000, 1), 50); % Create histogram from a normal distribution.
g = 1 / sqrt(2 * pi) * exp(-0.5 * x .^ 2); % pdf of the normal distribution

% METHOD 1: DIVIDE BY SUM
figure(1)
bar(x, f / sum(f)); hold on
plot(x, g, 'r'); hold off

% METHOD 2: DIVIDE BY AREA
figure(2)
bar(x, f / trapz(x, f)); hold on
plot(x, g, 'r'); hold off

Vous pouvez voir par vous-même quelle méthode convient à la bonne réponse (courbe rouge).

enter image description here

Une autre méthode (plus simple que la méthode 2) pour normaliser l'histogramme consiste à diviser par sum(f * dx), qui exprime l'intégrale de la fonction de densité de probabilité, c'est-à-dire.

% METHOD 3: DIVIDE BY AREA USING sum()
figure(3)
dx = diff(x(1:2))
bar(x, f / sum(f * dx)); hold on
plot(x, g, 'r'); hold off
120
abcd

Depuis 2014b, Matlab a ces routines de normalisation intégrées de manière native dans la fonction histogram (voir le fichier aide) les 6 routines offertes par cette fonction). Voici un exemple utilisant la normalisation PDF (la somme de tous les bacs est égale à 1).

data = 2*randn(5000,1) + 5;             % generate normal random (m=5, std=2)
h = histogram(data,'Normalization','pdf')   % PDF normalization

Le correspondant PDF est

Nbins = h.NumBins;
edges = h.BinEdges; 
x = zeros(1,Nbins);
for counter=1:Nbins
    midPointShift = abs(edges(counter)-edges(counter+1))/2;
    x(counter) = edges(counter)+midPointShift;
end

mu = mean(data);
sigma = std(data);

f = exp(-(x-mu).^2./(2*sigma^2))./(sigma*sqrt(2*pi));

Les deux ensemble donne

hold on;
plot(x,f,'LineWidth',1.5)

enter image description here

Une amélioration qui pourrait très bien être due au succès de la question et de la réponse acceptée !


EDIT - L'utilisation de hist et histc est non recommandé maintenant, et histogram devrait être utilisé à la place. Attention, aucune des 6 façons de créer des bacs avec cette nouvelle fonction ne produira les bacs hist et histc. Il existe un script Matlab pour mettre à jour l'ancien code afin qu'il s'adapte à la manière dont histogram est appelé (bin bords au lieu de bin centres - lien ). Ce faisant, on peut comparer les méthodes de normalisation pdf de @abcd (trapz et sum) et Matlab (pdf).

La méthode de normalisation 3 pdf donne des résultats presque identiques (dans la plage de eps) .

TESTER:

A = randn(10000,1);
centers = -6:0.5:6;
d = diff(centers)/2;
edges = [centers(1)-d(1), centers(1:end-1)+d, centers(end)+d(end)];
edges(2:end) = edges(2:end)+eps(edges(2:end));

figure;
subplot(2,2,1);
hist(A,centers);
title('HIST not normalized');

subplot(2,2,2);
h = histogram(A,edges);
title('HISTOGRAM not normalized');

subplot(2,2,3)
[counts, centers] = hist(A,centers); %get the count with hist
bar(centers,counts/trapz(centers,counts))
title('HIST with PDF normalization');


subplot(2,2,4)
h = histogram(A,edges,'Normalization','pdf')
title('HISTOGRAM with PDF normalization');

dx = diff(centers(1:2))
normalization_difference_trapz = abs(counts/trapz(centers,counts) - h.Values);
normalization_difference_sum = abs(counts/sum(counts*dx) - h.Values);

max(normalization_difference_trapz)
max(normalization_difference_sum)

enter image description here

La différence maximale entre la nouvelle normalisation PDF et la précédente est de 5.5511e-17.

23
marsei

hist peut non seulement tracer un histogramme, mais aussi vous renvoyer le nombre d'éléments contenus dans chaque groupe. Vous pouvez ainsi obtenir ce nombre, le normaliser en divisant chaque groupe par le total et en représentant le résultat à l'aide de bar. Exemple:

Y = Rand(10,1);
C = hist(Y);
C = C ./ sum(C);
bar(C)

ou si vous voulez un one-liner:

bar(hist(Y) ./ sum(hist(Y)))

Documentation:

Edit: Cette solution répond à la question Comment avoir la somme de tous les bacs égale à 1 . Cette approximation n’est valable que si la taille de votre corbeille est petite par rapport à la variance de vos données. La somme utilisée ici correspond à une formule simple en quadrature, les plus complexes pouvant être utilisées comme trapz comme proposé par R. M.

11
Simon
[f,x]=hist(data)

La zone pour chaque barre individuelle est hauteur * largeur. Puisque MATLAB choisira des points équidistants pour les barres, la largeur est la suivante:

delta_x = x(2) - x(1)

Maintenant, si nous résumons toutes les barres individuelles, la surface totale apparaîtra comme

A=sum(f)*delta_x

Donc, le tracé correctement mis à l'échelle est obtenu par

bar(x, f/sum(f)/(x(2)-x(1)))
5
Moppi

Le domaine abcd`s PDF n’est pas ce qui est impossible, comme le soulignent de nombreux commentaires. Des hypothèses formulées dans de nombreuses réponses ici.

  1. Supposons une distance constante entre les arêtes consécutives.
  2. La probabilité sous pdf devrait être 1. La normalisation devrait être effectuée comme Normalization avec probability, et non comme Normalization avec pdf, dans l'histogramme. () et hist ().

Fig. 1 Sortie de l'approche hist (), Fig. 2 Sortie de l'histogramme ()

enter image description hereenter image description here

L'amplitude max diffère entre deux approches, ce qui suggère qu'il y a une erreur dans l'approche de hist () car l'approche de histogram () utilise la normalisation standard. Je suppose que l’erreur avec hist () ici est de normaliser partiellement pdf, pas complètement comme probability.

Code avec hist () [obsolète]

Quelques remarques

  1. Première vérification: sum(f)/N donne 1 Si Nbins défini manuellement.
  2. pdf nécessite la largeur de la corbeille (dx) dans le graphe g

Code

%http://stackoverflow.com/a/5321546/54964
N=10000;
Nbins=50;
[f,x]=hist(randn(N,1),Nbins); % create histogram from ND

%METHOD 4: Count Densities, not Sums!
figure(3)
dx=diff(x(1:2)); % width of bin
g=1/sqrt(2*pi)*exp(-0.5*x.^2) .* dx; % pdf of ND with dx
% 1.0000
bar(x, f/sum(f));hold on
plot(x,g,'r');hold off

La sortie est illustrée à la Fig. 1.

Code avec histogramme ()

Quelques remarques

  1. Première vérification: a) sum(f) est 1 Si Nbins ajusté avec la normalisation de l'histogramme () sous forme de probabilité, b) sum(f)/N est égal à 1 si Nbins est défini manuellement sans normalisation.
  2. pdf nécessite la largeur de la corbeille (dx) dans le graphe g

Code

%%METHOD 5: with histogram()
% http://stackoverflow.com/a/38809232/54964
N=10000;

figure(4);
h = histogram(randn(N,1), 'Normalization', 'probability') % hist() deprecated!
Nbins=h.NumBins;
edges=h.BinEdges; 
x=zeros(1,Nbins);
f=h.Values;
for counter=1:Nbins
    midPointShift=abs(edges(counter)-edges(counter+1))/2; % same constant for all
    x(counter)=edges(counter)+midPointShift;
end
dx=diff(x(1:2)); % constast for all
g=1/sqrt(2*pi)*exp(-0.5*x.^2) .* dx; % pdf of ND
% Use if Nbins manually set
%new_area=sum(f)/N % diff of consecutive edges constant
% Use if histogarm() Normalization probability
new_area=sum(f)
% 1.0000
% No bar() needed here with histogram() Normalization probability
hold on;
plot(x,g,'r');hold off

La sortie sur la figure 2 et la sortie attendue est atteinte: zone 1.0000.

Matlab: 2016a
Système: Linux Ubuntu 16.04 64 bit
Linux noyau 4.6

Pour certaines distributions, Cauchy, je pense que j’ai trouvé que trapz surestimerait la zone, et donc le pdf changera en fonction du nombre de bacs sélectionnés. Dans quel cas je fais

[N,h]=hist(q_f./theta,30000); % there Is a large range but most of the bins will be empty
plot(h,N/(sum(N)*mean(diff(h))),'+r')
1
user1240280

Il existe un excellent guide en trois parties pour Ajustements d'histogramme dans MATLAB ( lien original cassé , lien archive.org ), la première partie est sur l'histogramme. Étirage.

1
anna