Python - Matplotlib: normalize axis when plotting a Probability Density Function

25,795

the y-axis is normed in a way, that the area under the curve is one. And adding equal weights for every data point makes no sense if you normalize anyway with normed=True.

first you need to shift your data to 0:

 lines -= mean(lines)

then plot it.

ythis should be a working minimal example:

import numpy as np                                                               
from numpy.random import normal                                                  
import matplotlib.pyplot as plt
from scipy.stats import norm                                                  

# gaussian distributed random numbers with mu =4 and sigma=2                     
x = normal(4, 2, 10000)                                                            

mean = np.mean(x)
sigma = np.std(x)

x -= mean 

x_plot = np.linspace(min(x), max(x), 1000)                                                               

fig = plt.figure()                                                               
ax = fig.add_subplot(1,1,1)                                                      

ax.hist(x, bins=50, normed=True, label="data")
ax.plot(x_plot, norm.pdf(x_plot, mean, sigma), 'r-', label="pdf")                                                          

ax.legend(loc='best')

x_ticks = np.arange(-4*sigma, 4.1*sigma, sigma)                                  
x_labels = [r"${} \sigma$".format(i) for i in range(-4,5)]                       

ax.set_xticks(x_ticks)                                                           
ax.set_xticklabels(x_labels)                                                     

plt.show() 

output image is this: plot outout

and you have too much imports. you import decimals twice, one time even with * and then numpy, pyplot and scipy are included in pylab. Also why import the whole scipy.stats and then again import just norm from it?

Share:
25,795
Informatico_Sano
Author by

Informatico_Sano

Student that likes scripting.

Updated on July 25, 2020

Comments

  • Informatico_Sano
    Informatico_Sano almost 4 years

    I'm using Python and some of its extensions to get and plot the Probability Density Function. While I manage to plot it, in its form, at least, I don't manage to succeed on scalating the axis.

    import decimal
    import numpy as np
    import scipy.stats as stats
    import pylab as pl
    import matplotlib.pyplot as plt
    from decimal import *
    from scipy.stats import norm
    
    lines=[]
    
    fig, ax = plt.subplots(1, 1)
    mean, var, skew, kurt = norm.stats(moments='mvsk')
    
    #Here I delete some lines aimed to fill the list with values
    
    Long = len(lines)
    Maxim = max(lines) #MaxValue
    Minim = min(lines) #MinValue
    av = np.mean(lines) #Average
    StDev = np.std(lines) #Standard Dev.
    
    x = np.linspace(Minim, Maxim, Long)
    ax.plot(x, norm.pdf(x, av, StDev),'r-', lw=3, alpha=0.9, label='norm pdf')
    
    weights = np.ones_like(lines)/len(lines)
    
    ax.hist(lines, weights = weights, normed=True, histtype='stepfilled', alpha=0.2)
    ax.legend(loc='best', frameon=False)
    plt.show()
    

    The result is Plot obtained

    While I would like to have it expressed - In the x-axis centered in 0 and related to the standard deviation - In the y-axis, related to the histogram and the %s (normalized to 1)
    For the x-axis as the image below Plot wished

    And like this last image for the y-axis Y-axis wished

    I've managed to escalate the y-axis in a histogram by plotting it individually with the instruction weights = weights and setting it into the plot, but I can't do it here. I include it in the code but actually it does nothing in this case.

    Any help would be appreciated

  • Informatico_Sano
    Informatico_Sano almost 10 years
    Hi @MaxNoe and thanks for the answer. To begin with, I get the idea of substracting the average of every element, but as it is a set of values that way is not correct. I think doing lines=[x-av for x in lines] fixes that. Anyway, I don't manage to adapt my code to that and I manage to plot but I obtain a very bad result. You mean that I only have to 'parse' the ax.plot(...) line to your code? Could you please add the plot missing line(s) to your solution? Thanks in advance
  • MaxNoe
    MaxNoe almost 10 years
    I edited the code to be a working minimal example and added the plot
  • Informatico_Sano
    Informatico_Sano almost 10 years
    Right, actually it does what I asked about the axis in the title and works perfectly with a histogram. Just a small problem that I face now, I can't plot the probability density function there, if I do that it losses its shape in fact. I use your mean and your st. dev, but I don't succeed with it. How should I do to add it? Thanks for your answers
  • MaxNoe
    MaxNoe almost 10 years
    what do you mean with 'it looses its shape' ?
  • Informatico_Sano
    Informatico_Sano almost 10 years
    I mean that the pdf as the one I plotted in the question, when I try to adapt it to your code and plot it there, on the same figure as the histogram, the result is not a Gaussian/bell curve. I'm not sure what am I doing wrong to plot it there also...
  • MaxNoe
    MaxNoe almost 10 years
    do you want to fit a guassian bell to the histogram? Or just Plot the gaussian bell with mu=mean(x) and sigma=std(x)?
  • MaxNoe
    MaxNoe almost 10 years
    if you use scipy.stats.norm.pdf, you will just plot a gaussian bell with mean=mean(x) and sigma=std(x). And that works for me, I edited the post.
  • Informatico_Sano
    Informatico_Sano almost 10 years
    Fit the the histogram into the bell and measure it with %s in the y-axis, I was searching for that exactly. I have to figure out why it doesn't work my given values, but I'll work on it tonight. Thank you very much for your answers.
  • MaxNoe
    MaxNoe almost 10 years
    what do you mean with %s? You have a continious probability function for the gaussian. If you want to completely normalize it to the standard gaussian divide the values by the standard deviation. But whats then the point? Do you want a histogram of a standard gaussian or of your data?
  • Informatico_Sano
    Informatico_Sano almost 10 years
    I have a set of given values, and I want the PDF function of the set measured like this: - On the x-axis, measured in function of the St. Dev. - On the y-axis, display the probability of appearance (maximum in 0*StDev) - Desirably the histogram of values fitted into it
  • MaxNoe
    MaxNoe almost 10 years
    the probability density is not the probability of appearance at this point, so your y-axis cannot be the probability of appearance if you plot an unbinned pdf. If you integrate the pdf over a delta, you get the probability of appearance for this delta.
  • Informatico_Sano
    Informatico_Sano over 9 years
    Hi again Max, do you know how to 'cut' the plot of the histogram between two limits while mantaining the P.D.F the exact way as it is now? For example drawing the histogtam here between -2*sigma and 2*sigma. Thanks in advance.
  • MaxNoe
    MaxNoe over 9 years
    You can give it the range option. , range=[-2*sigma,2 *sigma]