【问题标题】:How to plot normal distribution如何绘制正态分布
【发布时间】:2012-04-25 15:44:01
【问题描述】:

给定一个均值和一个方差,是否有一个简单的函数调用来绘制正态分布?

【问题讨论】:

    标签: python matplotlib


    【解决方案1】:
    import matplotlib.pyplot as plt
    import numpy as np
    import scipy.stats as stats
    import math
    
    mu = 0
    variance = 1
    sigma = math.sqrt(variance)
    x = np.linspace(mu - 3*sigma, mu + 3*sigma, 100)
    plt.plot(x, stats.norm.pdf(x, mu, sigma))
    plt.show()
    

    【讨论】:

    • 我没有内联选项,所以需要:%matplotlib inline 让情节显示出来
    • 为避免出现弃用警告,现在您应该使用scipy.stats.norm.pdf(x, mu, sigma) 而不是mlab.normpdf(x, mu, sigma)
    • 另外:当你已经导入numpy并且可以使用np.sqrt时,为什么还要导入math
    • @user8408080:虽然性能在这里不是问题,但我倾向于使用math 进行标量运算,因为例如,math.sqrt 在标量上运行时比np.sqrt 快一个数量级.
    • @Hamid:我怀疑你可以将 Y 轴更改为 0 到 100 之间的数字。这是表示概率密度函数的正态分布曲线。 Y 轴值表示概率密度。曲线下的总面积导致概率值为 1。由于它所代表的内容,您甚至不会在 Y 轴上获得高达 1 的值。我希望这是有道理的。
    【解决方案2】:

    我认为没有一个函数可以在一次调用中完成所有这些。不过你可以在scipy.stats找到高斯概率密度函数。

    所以我能想到的最简单的方法是:

    import numpy as np
    import matplotlib.pyplot as plt
    from scipy.stats import norm
    
    # Plot between -10 and 10 with .001 steps.
    x_axis = np.arange(-10, 10, 0.001)
    # Mean = 0, SD = 2.
    plt.plot(x_axis, norm.pdf(x_axis,0,2))
    plt.show()
    

    来源:

    【讨论】:

    • 您应该将norm.pdf 更改为norm(0, 1).pdf。这使得更容易适应其他情况/理解这会生成一个表示随机变量的对象。
    【解决方案3】:

    Unutbu 的答案是正确的。 但是因为我们的平均值可能大于或小于零,所以我仍然想更改它:

    x = np.linspace(-3 * sigma, 3 * sigma, 100)
    

    到这里:

    x = np.linspace(-3 * sigma + mean, 3 * sigma + mean, 100)
    

    【讨论】:

      【解决方案4】:

      如果您更喜欢循序渐进的方法,您可以考虑如下解决方案

      import numpy as np
      import matplotlib.pyplot as plt
      
      mean = 0; std = 1; variance = np.square(std)
      x = np.arange(-5,5,.01)
      f = np.exp(-np.square(x-mean)/2*variance)/(np.sqrt(2*np.pi*variance))
      
      plt.plot(x,f)
      plt.ylabel('gaussian distribution')
      plt.show()
      

      【讨论】:

        【解决方案5】:

        您可以轻松获得 cdf。所以通过 cdf 生成 pdf

            import numpy as np
            import matplotlib.pyplot as plt
            import scipy.interpolate
            import scipy.stats
        
            def setGridLine(ax):
                #http://jonathansoma.com/lede/data-studio/matplotlib/adding-grid-lines-to-a-matplotlib-chart/
                ax.set_axisbelow(True)
                ax.minorticks_on()
                ax.grid(which='major', linestyle='-', linewidth=0.5, color='grey')
                ax.grid(which='minor', linestyle=':', linewidth=0.5, color='#a6a6a6')
                ax.tick_params(which='both', # Options for both major and minor ticks
                                top=False, # turn off top ticks
                                left=False, # turn off left ticks
                                right=False,  # turn off right ticks
                                bottom=False) # turn off bottom ticks
        
            data1 = np.random.normal(0,1,1000000)
            x=np.sort(data1)
            y=np.arange(x.shape[0])/(x.shape[0]+1)
        
            f2 = scipy.interpolate.interp1d(x, y,kind='linear')
            x2 = np.linspace(x[0],x[-1],1001)
            y2 = f2(x2)
        
            y2b = np.diff(y2)/np.diff(x2)
            x2b=(x2[1:]+x2[:-1])/2.
        
            f3 = scipy.interpolate.interp1d(x, y,kind='cubic')
            x3 = np.linspace(x[0],x[-1],1001)
            y3 = f3(x3)
        
            y3b = np.diff(y3)/np.diff(x3)
            x3b=(x3[1:]+x3[:-1])/2.
        
            bins=np.arange(-4,4,0.1)
            bins_centers=0.5*(bins[1:]+bins[:-1])
            cdf = scipy.stats.norm.cdf(bins_centers)
            pdf = scipy.stats.norm.pdf(bins_centers)
        
            plt.rcParams["font.size"] = 18
            fig, ax = plt.subplots(3,1,figsize=(10,16))
            ax[0].set_title("cdf")
            ax[0].plot(x,y,label="data")
            ax[0].plot(x2,y2,label="linear")
            ax[0].plot(x3,y3,label="cubic")
            ax[0].plot(bins_centers,cdf,label="ans")
        
            ax[1].set_title("pdf:linear")
            ax[1].plot(x2b,y2b,label="linear")
            ax[1].plot(bins_centers,pdf,label="ans")
        
            ax[2].set_title("pdf:cubic")
            ax[2].plot(x3b,y3b,label="cubic")
            ax[2].plot(bins_centers,pdf,label="ans")
        
            for idx in range(3):
                ax[idx].legend()
                setGridLine(ax[idx])
        
            plt.show()
            plt.clf()
            plt.close()
        

        【讨论】:

          【解决方案6】:

          我刚刚回到这个问题,我必须安装 scipy,因为 matplotlib.mlab 在尝试上面的示例时给了我错误消息 MatplotlibDeprecationWarning: scipy.stats.norm.pdf。所以现在的示例是:

          %matplotlib inline
          import math
          import matplotlib.pyplot as plt
          import numpy as np
          import scipy.stats
          
          
          mu = 0
          variance = 1
          sigma = math.sqrt(variance)
          x = np.linspace(mu - 3*sigma, mu + 3*sigma, 100)
          plt.plot(x, scipy.stats.norm.pdf(x, mu, sigma))
          
          plt.show()
          

          【讨论】:

            【解决方案7】:

            改用 seaborn 我正在使用 seaborn 的 distplot,mean=5 std=3 of 1000 个值

            value = np.random.normal(loc=5,scale=3,size=1000)
            sns.distplot(value)
            

            你会得到一条正态分布曲线

            【讨论】:

            • 当您收到有关弃用此功能的警告时,请改用 histplot。保罗
            【解决方案8】:

            我认为设置高度很重要,所以创建了这个函数:

            def my_gauss(x, sigma=1, h=1, mid=0):
                from math import exp, pow
                variance = pow(sdev, 2)
                return h * exp(-pow(x-mid, 2)/(2*variance))
            

            其中sigma 是标准差,h 是高度,mid 是平均值。

            这是使用不同高度和偏差的结果:

            【讨论】:

              【解决方案9】:
              import math  
              import matplotlib.pyplot as plt
              import numpy
              import pandas as pd
              
              
              def normal_pdf(x, mu=0, sigma=1):
                  sqrt_two_pi = math.sqrt(math.pi * 2)
                  return math.exp(-(x - mu) ** 2 / 2 / sigma ** 2) / (sqrt_two_pi * sigma)
              
              
              df = pd.DataFrame({'x1': numpy.arange(-10, 10, 0.1), 'y1': map(normal_pdf, numpy.arange(-10, 10, 0.1))})
              
              plt.plot('x1', 'y1', data=df, marker='o', markerfacecolor='blue', markersize=5, color='skyblue', linewidth=1)
              plt.show()
              

              【讨论】: