Python plot distribución normal


116

Dada una media y una varianza, ¿existe una llamada de función simple que trazará una distribución normal?

Respuestas:


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

distribución de gases, la media es 0 varianza 1


No tenía la opción en línea, así que lo necesitaba: %matplotlib inlinepara que aparezca la trama
hum3

Para evitar advertencias de desaprobación, ahora debe usar en scipy.stats.norm.pdf(x, mu, sigma)lugar demlab.normpdf(x, mu, sigma)
Leonardo Gonzalez

Además: ¿Por qué importa mathcuando ya lo ha importado numpyy podría utilizarlo np.sqrt?
user8408080

1
@ user8408080: Aunque el rendimiento no es un problema aquí, tiendo a usarlo mathpara operaciones escalares ya que, por ejemplo, math.sqrtes más rápido que np.sqrtcuando se opera en escalares.
unutbu

¿Cómo puedo cambiar los ejes Y a números entre 0 y 100?
Hamid

54

No creo que haya una función que haga todo eso en una sola llamada. Sin embargo, puede encontrar la función de densidad de probabilidad gaussiana en scipy.stats.

Entonces, la forma más sencilla que se me ocurrió es:

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

Fuentes:


2
Probablemente debería cambiar norm.pdfa norm(0, 1).pdf. Esto facilita la adaptación a otros casos / entender que esto genera un objeto que representa una variable aleatoria.
Martin Thoma

10

Use seaborn en su lugar, estoy usando distplot de seaborn con media = 5 std = 3 de 1000 valores

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

Obtendrá una curva de distribución normal


9

La respuesta de Unutbu es correcta. Pero debido a que nuestra media puede ser más o menos que cero, todavía me gustaría cambiar esto:

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

a esto :

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

5

Si prefiere utilizar un enfoque paso a paso, podría considerar una solución como la siguiente

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

1

Acabo de volver a esto y tuve que instalar scipy ya que matplotlib.mlab me dio el mensaje de error MatplotlibDeprecationWarning: scipy.stats.norm.pdfal probar el ejemplo anterior. Entonces la muestra es ahora:

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

1

Creo que es importante establecer la altura, así que creé esta función:

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

Donde sigmaes la desviación estándar, hes la altura y mides la media.

Aquí está el resultado usando diferentes alturas y desviaciones:

ingrese la descripción de la imagen aquí


0

puede obtener CDF fácilmente. entonces pdf a través de cdf

    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()
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.