web-dev-qa-db-fra.com

Adapter une fonction gaussienne

J'ai un histogramme (voir ci-dessous) et j'essaie de trouver l'écart moyen et standard ainsi que le code qui correspond à une courbe pour mon histogramme. Je pense que quelque chose dans SciPy ou matplotlib peut aider, mais chaque exemple que j'ai essayé ne fonctionne pas. 

import matplotlib.pyplot as plt
import numpy as np

with open('gau_b_g_s.csv') as f:
    v = np.loadtxt(f, delimiter= ',', dtype="float", skiprows=1, usecols=None)

fig, ax = plt.subplots()

plt.hist(v, bins=500, color='#7F38EC', histtype='step')

plt.title("Gaussian")
plt.axis([-1, 2, 0, 20000])

plt.show()
20
user1496646

Regardez cette réponse pour ajuster des courbes arbitraires aux données. En gros, vous pouvez utiliser scipy.optimize.curve_fit pour adapter la fonction que vous souhaitez à vos données. Le code ci-dessous montre comment adapter une gaussienne à des données aléatoires (crédit de this message de la liste de diffusion de SciPy-User).

import numpy
from scipy.optimize import curve_fit
import matplotlib.pyplot as plt

# Define some test data which is close to Gaussian
data = numpy.random.normal(size=10000)

hist, bin_edges = numpy.histogram(data, density=True)
bin_centres = (bin_edges[:-1] + bin_edges[1:])/2

# Define model function to be used to fit to the data above:
def gauss(x, *p):
    A, mu, sigma = p
    return A*numpy.exp(-(x-mu)**2/(2.*sigma**2))

# p0 is the initial guess for the fitting coefficients (A, mu and sigma above)
p0 = [1., 0., 1.]

coeff, var_matrix = curve_fit(gauss, bin_centres, hist, p0=p0)

# Get the fitted curve
hist_fit = gauss(bin_centres, *coeff)

plt.plot(bin_centres, hist, label='Test data')
plt.plot(bin_centres, hist_fit, label='Fitted data')

# Finally, lets get the fitting parameters, i.e. the mean and standard deviation:
print 'Fitted mean = ', coeff[1]
print 'Fitted standard deviation = ', coeff[2]

plt.show()
35
Chris

Vous pouvez essayer d’estimer le modèle de mélange gaussien comme indiqué ci-dessous:

import numpy as np
import sklearn.mixture

gmm = sklearn.mixture.GMM()

# sample data
a = np.random.randn(1000)

# result
r = gmm.fit(a[:, np.newaxis]) # GMM requires 2D data as of sklearn version 0.16
print("mean : %f, var : %f" % (r.means_[0, 0], r.covars_[0, 0]))

Référence: http://scikit-learn.org/stable/modules/mixture.html#mixture

Notez que de cette manière, vous n'avez pas besoin d'estimer votre distribution d'échantillon avec un histogramme.

13
Nicolas Barbey

C'est une vieille question, mais pour quiconque cherche juste à tracer une densité digne d'une série, vous pouvez essayer .plot(kind='kde') de matplotlib. Docs ici .

Exemple avec des pandas:

mydf.x.plot(kind='kde')
2
misterte

Je ne sais pas quelle est votre contribution, mais si votre échelle d'axe des ordonnées est trop grande (20000), essayez de réduire ce nombre. Le code suivant fonctionne pour moi:

import matplotlib.pyplot as plt
import numpy as np

#created my variable
v = np.random.normal(0,1,1000)


fig, ax = plt.subplots()


plt.hist(v, bins=500, normed=1, color='#7F38EC', histtype='step')

#plot
plt.title("Gaussian")
plt.axis([-1, 2, 0, 1]) #changed 20000 to 1

plt.show()

Modifier:

Si vous voulez connaître le nombre réel de valeurs sur l’axe des y, vous pouvez définir normed=0. Et je voudrais juste me débarrasser de la plt.axis([-1, 2, 0, 1]).

import matplotlib.pyplot as plt
import numpy as np

#function
v = np.random.normal(0,1,500000)


fig, ax = plt.subplots()

# changed normed=1 to normed=0
plt.hist(v, bins=500, normed=0, color='#7F38EC', histtype='step')

#plot
plt.title("Gaussian")
#plt.axis([-1, 2, 0, 20000]) 

plt.show()
0
Akavall