2016-05-12 1 views
3

J'essaie d'insérer une loi exponentielle dans mes données. Mon échantillon (x,y) est plutôt compliqué à expliquer, donc pour la compréhension générale et la reproductibilité je dirai que: les deux variables sont float et continuous, 0<=x<=100, et 0<=y<=1.Mauvais graphe avec scipy.optimize.curve_fit (similaire à la moyenne mobile)

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

#ydata=[...] is my list with y values, which contains 0 values 
#xdata=[...] is my list with x values 

transf_y=[] 
for i in range(len(ydata)): 
    transf_y.append(ydata[i]+0.00001) #Adding something to avoid zero values 

x=numpy.array(xdata,dtype=float) 
y=numpy.array(transf_y,dtype=float) 

def func(x, a, c, d): 
    return a * numpy.exp(-c*x)+d 

popt, pcov = curve_fit(func, x, y,p0 = (1, 1e-6, 1)) 

print ("a = %s , c = %s, d = %s" % (popt[0], popt[1], popt[2])) 

xx = numpy.linspace(300, 6000, 1000) 
yy = func(xx, *popt) 

plt.plot(x,y,label='Original Data') 
plt.plot(xx, yy, label="Fitted Curve") 

plt.legend(loc='upper left') 
plt.show() 

Maintenant, ma courbe ajustée ne ressemble en rien à une courbe exponentielle ajustée. Au contraire, il ressemble à une courbe moyenne mobile comme si cette courbe a été ajoutée en tant que courbe de tendance sur Excel. Quel pourrait être le problème? Si nécessaire, je trouverai un moyen de rendre les jeux de données disponibles pour rendre l'exemple reproductible.

C'est ce que je sors de mon code (je ne sais même pas pourquoi je reçois trois éléments dans la légende alors que seulement deux sont tracés, au moins en apparence): enter image description here

Répondre

4

enter image description here Une multitude de choses:

  1. votre parcelle met en scène une donnée d'origine deux fois et aucune donnée équipée perceptible
  2. vos données ne semble pas être commandé, je suppose que c'est pourquoi vous obtenez des lignes Zickzack
  3. dans votre exemple, votre parcelle prédit sera dans l'intervalle compris entre 300 et 6000 alors que vos données brutes 0 < = x < = 100

Cela mis à part, votre code est plus ou moins correcte et fonctionne.

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

xdata=[100.0, 0.0, 90.0, 20.0, 80.0] #is my list with y values, which contains 0 values - edit, you need some raw data which you fit, I inserted some 
ydata=[0.001, 1.0, 0.02, 0.56, 0.03] #is my list with x values 

transf_y=[] 
for i in range(len(ydata)): 
    transf_y.append(ydata[i]+0.00001) #Adding something to avoid zero values 

x1=numpy.array(xdata,dtype=float) 
y1=numpy.array(transf_y,dtype=float) 

def func(x, a, c, d): 
    return a * numpy.exp(-c*x)+d 

popt, pcov = curve_fit(func, x1, y1,p0 = (1, 1e-6, 1)) 

print ("a = %s , c = %s, d = %s" % (popt[0], popt[1], popt[2])) 

#ok, sorting your data 
pairs = [] 
for i, j in zip(x1, y1): 
    pairs.append([i,j]) 

sortedList = sorted(pairs, key = lambda x:x[0]) 
sorted_x = numpy.array(sortedList)[:,0] 
sorted_y = numpy.array(sortedList)[:,1] 


#adjusting interval to the limits of your raw data 
xx = numpy.linspace(0, 100.0, 1000) 
yy = func(xx, *popt) 


#and everything looks fine 
plt.plot(sorted_x,sorted_y, 'o',label='Original Data') 
plt.plot(xx,yy,label='Fitted Data') 

plt.legend(loc='upper left') 
plt.show() 
+1

Le seul gros problème était que mes données n'étaient pas triées. Je pensais sincèrement que c'était fait automatiquement. J'avais vraiment tort. – FaCoffee

+1

Oui. Et cela ne fait que salir les parcelles, le montage est parfait. –