.

.

.

.

.

HealthyNumerics

HealthPoliticsEconomics | Quant Analytics | Numerics

Basic Stats 31: Linear Regression


Einfache lineare Regression

Einfache Methoden für Datenfluss und Statistik mit Python, Pandas, NumPy, StatsModels, Seaborn, Matplotlib

Das Beispiel stammt aus:

Reinhold Hatzinger, Kurt Hornik, Herbert Nagel (2011): R - Einführung durch angewandte Statistik, Pearson Studium, 465pp, ISBN978-3-8632-6599-1 , siehe auch hier

Dort könnten auch unter Extras/CWS die Input-Daten gefunden werden. Das nachfolgende Beispiel ist aus Kapitel 9.2 (Mehrere metrische Variablen), die verwendete Datendatei: gewicht.csv.

Im Beispiel liegen Daten zum Körpergewicht vor, das einerseits erfragt und anderseits mittels Waage gemessen wurde.

import numpy  as np
import pandas as pd
import statsmodels.api as sm
import statsmodels.formula.api as smf
import seaborn as sns
import matplotlib.pyplot as plt
sns.set(style="ticks")
%matplotlib inline

Daten

angabe;waage
83;88,0
64;70,1
94;94,2
73;76,8
79;81,1

Die Daten liegen in einer CSV-Datei vor. Oben sind nur die ersten paar Zeilen davon angezeigt. Sie können mit pd.read_csv direkt in ein Pandas DataFrame eingelesen werden. Dabei muss mitgeteilt werden, dass ";" als Trennzeichen auftritt. In der zweiten Spalte müssen die "," durch "." ersetzt werden. Da die zweite Spalte danach als string vorliegt, wird sie mit pd.to_numeric in einen numerischen Wert umgewandelt.

f10Dir = r"C:/gcg/7_Wissen_T/eBücher/R-HatzingerHornikNagel/R-Begleitmaterial/Daten\\"
f10Name= r"gewicht.csv"
f10 = f10Dir+f10Name

dg = pd.read_csv(open(f10, newline=''), sep=';') # set ; as delimiter and import the data as pd.DataFrame
dg['waage'] = dg['waage'].str.replace(",",".")   # replace the coma by a point
dg['waage'] = pd.to_numeric(dg['waage'])         # transform the string into numerical value

dg.head(4)                                       # display the first few lines of the DataFrame
angabe waage
0 83 88.0
1 64 70.1
2 94 94.2
3 73 76.8

Darstellung der Daten

Mit Seaborn können die Daten dargestellt werden. Die Regressionsgerade sowie die Häufigkeitsverteilungen werden automatisch berechnet und geplottet.

sns.jointplot(x="waage", y="angabe", data= dg, kind="reg");

png

Parameter der Regressionsgerade

Wir berechnen nun die Regression mit StatsModels. Die gewünschte Regressionsbeziehung kann mit formula='angabe ~ waage ' in einem Format angegeben werden, wie es bei R üblich ist: y=angabe soll durch x=waage ausgedrückt werden. Die Ergebnisparameter liegen als pd.DataSeries vor, also ein 1-dimensionales DataFrame.

estimation = smf.ols(formula='angabe ~ waage ', data=dg).fit()
p = estimation.params
print(type(p))
print(p)
<class 'pandas.core.series.Series'>
Intercept   -3.522249
waage        1.015543
dtype: float64

Verwendung der Regressionsgerade

Mit den Regressionsparametern drücken wir die Regressionsgerade aus. Für die x-Werte bilden wir einen NumPy-array, und die y-Werte berechnen wir mit der Geradengleichung. Mit Matplotlib plotten wir die Daten und die Gerade.

x = np.linspace(0,120,2)
y = p[0] + p[1]*x
fig,ax = plt.subplots()
ax.plot(x,y,'-')
ax.plot(dg['waage'],dg['angabe'],'o')

png

Von den StatsModels-Ergebnissen drucken wir die vollständige Zusammenfassung aus.

estimation.summary()
OLS Regression Results
Dep. Variable: angabe R-squared: 0.970
Model: OLS Adj. R-squared: 0.969
Method: Least Squares F-statistic: 1529.
Date: Tue, 12 Sep 2017 Prob (F-statistic): 4.62e-38
Time: 16:14:35 Log-Likelihood: -112.78
No. Observations: 50 AIC: 229.6
Df Residuals: 48 BIC: 233.4
Df Model: 1
Covariance Type: nonrobust
coef std err t P>|t| [0.025 0.975]
Intercept -3.5222 2.132 -1.652 0.105 -7.808 0.764
waage 1.0155 0.026 39.107 0.000 0.963 1.068
Omnibus: 0.153 Durbin-Watson: 1.858
Prob(Omnibus): 0.926 Jarque-Bera (JB): 0.318
Skew: -0.105 Prob(JB): 0.853
Kurtosis: 2.671 Cond. No. 525.

Lineare Regression mit scipy

slope, intercept, r_value, p_value, std_err = st.linregress(dg['waage'], dg['angabe'])
print('scipy lingress: ',slope, intercept)
scipy lingress:  1.01554288925 -3.52224854645

Lineare Regression mit numpy

f_poly = np.polyfit(dg['waage'], dg['angabe'], 1)
print('numpy polyfit  : ', f_poly)
numpy polyfit  :  [ 1.01554289 -3.52224855]

Function fitting with scipy

from scipy.optimize import curve_fit
def func(x, a, b):  return a * x + b
popt, pcov = curve_fit(func, dg['waage'], dg['angabe'])
print(popt)
[ 1.01554289 -3.52224855]

```python

``````