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?

usuario1220022
fuente

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

unutbu
fuente
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:

lum
fuente
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

Tablero de Kaustuv
fuente
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)
Lucas359
fuente
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()
João Quintas
fuente
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()
hum3
fuente
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í

Eduardo Freitas
fuente
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()
johnInHome
fuente