web-dev-qa-db-fra.com

Python/Matplotlib: ajout d'une ligne de régression à un graphique en fonction de son intersection et de sa pente

Utilisation du petit jeu de données suivant:

bill = [34,108,64,88,99,51]
tip =  [5,17,11,8,14,5]  

J'ai calculé une droite de régression au meilleur ajustement (à la main). 

yi = 0.1462*x - 0.8188 #yi = slope(x) + intercept

J'ai tracé mes données d'origine en utilisant Matplotlib comme ceci:

scatter(bill,tip, color="black")
plt.xlim(20,120) #set ranges
plt.ylim(4,18)

#plot centroid point (mean of each variable (74,10))
line1 = plt.plot([74, 74],[0,10], ':', c="red")
line2 = plt.plot([0,74],[10,10],':', c="red")

plt.scatter(74,10, c="red")

#annotate the centroid point
plt.annotate('centroid (74,10)', xy=(74.1,10), xytext=(81,9),
        arrowprops=dict(facecolor="black", shrink=0.01),
        )

#label axes
xlabel("Bill amount ($)")
ylabel("Tip amount ($)")

#display plot
plt.show()

Je ne suis pas sûr de savoir comment obtenir la ligne de régression sur l'intrigue elle-même. Je suis conscient qu'il y a beaucoup de choses intégrées pour ajuster et afficher rapidement les lignes de meilleur ajustement, mais je l'ai fait comme pratique. Je sais que je peux commencer la ligne aux points '0,0.8188' (l'ordonnée à l'origine), mais je ne sais pas comment utiliser la valeur de pente pour compléter la ligne (définir les points de fin de la ligne).

Etant donné que pour chaque augmentation sur l'axe des x, la pente devrait augmenter de '0,1462'; pour les coordonnées de la ligne, j'ai essayé (0,0,8188) pour le point de départ et (100,14,62) pour le point final. Mais cette ligne ne passe pas par mon point centroïde. Il manque juste.

Cordialement, Jon

5
Jon

Le raisonnement dans la question partiellement correct. Ayant une fonction f(x) = a*x +b, vous pouvez prendre comme premier point l'interception avec l'axe des y (x = 0) comme (0, b) (ou (0,-0.8188) dans ce cas).
Tout autre point sur cette ligne est donné par (x, f(x)) ou (x, a*x+b). Donc, regarder le point x = 100 vous donnerait (100, f(100)), en connectant: (100, 0.1462*100-0.8188) = (100,13.8012). Dans le cas que vous décrivez dans la question, vous avez simplement oublié de prendre en compte la b.

Ce qui suit montre comment utiliser cette fonction pour tracer la ligne dans matplotlib:

import matplotlib.pyplot as plt
import numpy as np

bill = [34,108,64,88,99,51]
tip =  [5,17,11,8,14,5]  
plt.scatter(bill, tip)

#fit function
f = lambda x: 0.1462*x - 0.8188
# x values of line to plot
x = np.array([0,100])
# plot fit
plt.plot(x,f(x),lw=2.5, c="k",label="fit line between 0 and 100")

#better take min and max of x values
x = np.array([min(bill),max(bill)])
plt.plot(x,f(x), c="orange", label="fit line between min and max")

plt.legend()
plt.show()

 enter image description here

Bien sûr, l'ajustement peut aussi être fait automatiquement. Vous pouvez obtenir la pente et l'intercepter d'un appel à numpy.polyfit:

#fit function
a, b = np.polyfit(np.array(bill), np.array(tip), deg=1)
f = lambda x: a*x + b

Le reste de l'intrigue resterait le même.

définir l'ajustement de la fonction, obtenir les points de terminaison des données, mettre des nuplets à tracer ()

def fit(x):
    return 0.1462*x - 0.8188 #yi = slope(x) - intercept
xfit, yfit = (min(bill), max(bill)), (fit(min(bill)), fit(max(bill)))    
plt.plot(xfit, yfit,'b')
1
f5r5e5d

note rapide: Je pense que la formule pour la régression devrait être 

return 0.1462*x + 0.8188 #yi = slope(x) + intercept

Je veux dire + au lieu de -.

0
Enzo Calogero