python plot distribusi normal

116

Diberikan mean dan varians, apakah ada pemanggilan fungsi sederhana yang akan menggambarkan distribusi normal?

pengguna1220022
sumber

Jawaban:

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

distro gas, rata-rata adalah 0 varian 1

unutbu
sumber
Saya tidak memiliki opsi inline yang sangat dibutuhkan: %matplotlib inlineagar plotnya muncul
hum3
Untuk menghindari peringatan bantahan, sekarang Anda harus menggunakan scipy.stats.norm.pdf(x, mu, sigma)bukannyamlab.normpdf(x, mu, sigma)
Leonardo Gonzalez
Selain itu: Mengapa Anda mengimpor mathketika Anda sudah mengimpor numpydan dapat menggunakan np.sqrt?
pengguna8408080
1
@ user8408080: Meskipun kinerja tidak menjadi masalah di sini, saya cenderung menggunakan mathuntuk operasi skalar karena, misalnya, jauh math.sqrtlebih cepat daripada np.sqrtsaat beroperasi pada skalar.
unutbu
Bagaimana cara mengubah sumbu Y menjadi angka antara 0 hingga 100?
Hamid
54

Saya tidak berpikir ada fungsi yang melakukan semua itu dalam satu panggilan. Namun Anda dapat menemukan fungsi kepadatan probabilitas Gaussian di scipy.stats.

Jadi cara paling sederhana yang bisa saya lakukan adalah:

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

Sumber:

lum
sumber
2
Anda mungkin harus berubah norm.pdfmenjadi norm(0, 1).pdf. Ini membuatnya lebih mudah untuk menyesuaikan dengan kasus lain / untuk memahami bahwa ini menghasilkan objek yang mewakili variabel acak.
Martin Thoma
10

Gunakan seaborn sebagai gantinya saya menggunakan distplot dari seaborn dengan mean = 5 std = 3 dari 1000 nilai

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

Anda akan mendapatkan kurva distribusi normal

Kaustuv Dash
sumber
9

Jawaban Unutbu benar. Tetapi karena mean kita bisa lebih atau kurang dari nol, saya masih ingin mengubah ini:

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

untuk ini :

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

Jika Anda lebih suka menggunakan pendekatan langkah demi langkah, Anda dapat mempertimbangkan solusi seperti berikut

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
sumber
1

Saya baru saja kembali ke ini dan saya harus menginstal scipy karena matplotlib.mlab memberi saya pesan kesalahan MatplotlibDeprecationWarning: scipy.stats.norm.pdfketika mencoba contoh di atas. Jadi sampelnya sekarang:

%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
sumber
1

Saya percaya itu penting untuk mengatur ketinggian, jadi buatlah fungsi ini:

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

Dimana sigmadeviasi standar, hadalah tinggi danmid mean.

Berikut adalah hasil menggunakan ketinggian dan deviasi yang berbeda:

masukkan deskripsi gambar di sini

Eduardo Freitas
sumber
0

Anda bisa mendapatkan cdf dengan mudah. jadi pdf melalui 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
sumber