import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
data_url = 'https://raw.githubusercontent.com/PinkWink/ML_tutorial/master/dataset/ecommerce.csv'
data = pd.read_csv(data_url)
data.head()
| Address | Avatar | Avg. Session Length | Time on App | Time on Website | Length of Membership | Yearly Amount Spent | ||
|---|---|---|---|---|---|---|---|---|
| 0 | mstephenson@fernandez.com | 835 Frank Tunnel\nWrightmouth, MI 82180-9605 | Violet | 34.497268 | 12.655651 | 39.577668 | 4.082621 | 587.951054 |
| 1 | hduke@hotmail.com | 4547 Archer Common\nDiazchester, CA 06566-8576 | DarkGreen | 31.926272 | 11.109461 | 37.268959 | 2.664034 | 392.204933 |
| 2 | pallen@yahoo.com | 24645 Valerie Unions Suite 582\nCobbborough, D... | Bisque | 33.000915 | 11.330278 | 37.110597 | 4.104543 | 487.547505 |
| 3 | riverarebecca@gmail.com | 1414 David Throughway\nPort Jason, OH 22070-1220 | SaddleBrown | 34.305557 | 13.717514 | 36.721283 | 3.120179 | 581.852344 |
| 4 | mstephens@davidson-herman.com | 14023 Rodriguez Passage\nPort Jacobville, PR 3... | MediumAquaMarine | 33.330673 | 12.795189 | 37.536653 | 4.446308 | 599.406092 |
# 필요없는 데이터 삭제
data.drop(['Email','Address','Avatar'],axis=1, inplace=True)
data.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 500 entries, 0 to 499
Data columns (total 5 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Avg. Session Length 500 non-null float64
1 Time on App 500 non-null float64
2 Time on Website 500 non-null float64
3 Length of Membership 500 non-null float64
4 Yearly Amount Spent 500 non-null float64
dtypes: float64(5)
memory usage: 19.7 KB
plt.figure(figsize=(12,6))
sns.boxplot(data=data.iloc[:,:-1]);

#Yearly만 따로 확인
plt.figure(figsize=(10,4))
sns.boxplot(data=data['Yearly Amount Spent']);

# pairplot으로 확인
plt.figure(figsize=(12,6))
sns.pairplot(data=data);

# lmplot으로 확인해보기
plt.figure(figsize=(12,6))
sns.lmplot(x='Length of Membership', y='Yearly Amount Spent', data = data);

# 상관이 높은 멤버십 유지기간만 가지고 통계적 회귀
# statsmodels 패키지에 있는 ols 함수를 사용하면 간편하게 단순선형회귀 분석을 진행할 수 있다.
import statsmodels.api as sm
X = data['Length of Membership']
y = data['Yearly Amount Spent']
lm = sm.OLS(y,X).fit()
lm.summary()
| Dep. Variable: | Yearly Amount Spent | R-squared (uncentered): | 0.970 |
|---|---|---|---|
| Model: | OLS | Adj. R-squared (uncentered): | 0.970 |
| Method: | Least Squares | F-statistic: | 1.617e+04 |
| Date: | Tue, 17 Jan 2023 | Prob (F-statistic): | 0.00 |
| Time: | 15:22:54 | Log-Likelihood: | -2945.2 |
| No. Observations: | 500 | AIC: | 5892. |
| Df Residuals: | 499 | BIC: | 5897. |
| Df Model: | 1 | ||
| Covariance Type: | nonrobust |
| coef | std err | t | P>|t| | [0.025 | 0.975] | |
|---|---|---|---|---|---|---|
| Length of Membership | 135.6117 | 1.067 | 127.145 | 0.000 | 133.516 | 137.707 |
| Omnibus: | 1.408 | Durbin-Watson: | 1.975 |
|---|---|---|---|
| Prob(Omnibus): | 0.494 | Jarque-Bera (JB): | 1.472 |
| Skew: | 0.125 | Prob(JB): | 0.479 |
| Kurtosis: | 2.909 | Cond. No. | 1.00 |
위 회귀분석 결과에서 나오는 주요 결과물들의 설명
Dep. Variable: Dependent variable, 종속변수를 의미한다.Model: 모델링 방법을 뜻하고, OLS는 Ordinary Least Squares의 약자이다.No. Observations: Number of observations, 관찰표본 수, 즉 총 표본 수를 뜻한다. Df Residuals: DF는 Degree of Freedom, 자유도를 뜻하는데, DF Residuals는 전체 표본 수에서 측정되는 변수들(종속변수 및 독립변수)의 개수를 빼서 구한다. Df Model: 독립변수의 개수.R squared: R의 제곱이라는 뜻이고 결정계수를 의미한다. 전체 데이터 중 해당 회귀모델이 설명할 수 있는 데이터의 비율, 회귀식의 설명력을 나타낸다. SSTr/SST이나 상관계수 R을 제곱해서 구할 수 있다.Adj. R-squared : 독립변수가 여러 개인 다중회귀분석에서 사용Prob. F-Statistic : 회귀 모형에 대한 통계적 유의미성 검정, 이 값이 0.05 이하라면 모집단에서도 의미가 있다고 볼 수 있음.F-statistics: F통계량, MSR/MSE로 구할 수 있다. Prob: F통계량에 해당하는 P-value를 의미. # 회귀 모델 확인
pred = lm.predict(X)
sns.scatterplot(x=X, y=y)
plt.plot(X,pred,'r',ls='dashed',lw=3)

위의 값은 상수항이 없기 때문.
X에 열을 추가
X = np.c_[X, [1]*len(X)]
X[:5]
array([[4.08262063, 1. ],
[2.66403418, 1. ],
[4.1045432 , 1. ],
[3.12017878, 1. ],
[4.44630832, 1. ]])
#다시 fit시키기
lm = sm.OLS(y,X).fit()
lm.summary()
| Dep. Variable: | Yearly Amount Spent | R-squared: | 0.655 |
|---|---|---|---|
| Model: | OLS | Adj. R-squared: | 0.654 |
| Method: | Least Squares | F-statistic: | 943.9 |
| Date: | Tue, 17 Jan 2023 | Prob (F-statistic): | 4.81e-117 |
| Time: | 15:31:57 | Log-Likelihood: | -2629.9 |
| No. Observations: | 500 | AIC: | 5264. |
| Df Residuals: | 498 | BIC: | 5272. |
| Df Model: | 1 | ||
| Covariance Type: | nonrobust |
| coef | std err | t | P>|t| | [0.025 | 0.975] | |
|---|---|---|---|---|---|---|
| x1 | 64.2187 | 2.090 | 30.723 | 0.000 | 60.112 | 68.326 |
| const | 272.3998 | 7.675 | 35.492 | 0.000 | 257.320 | 287.479 |
| Omnibus: | 1.092 | Durbin-Watson: | 2.065 |
|---|---|---|---|
| Prob(Omnibus): | 0.579 | Jarque-Bera (JB): | 1.122 |
| Skew: | 0.037 | Prob(JB): | 0.571 |
| Kurtosis: | 2.780 | Cond. No. | 14.4 |
R-squared값과 AIC값이 낮아진 것을 알 수 있다.
pred = lm.predict(X)
sns.scatterplot(x=X[:,0],y=y)
plt.plot(X[:,0],pred,'r',ls='dashed',lw=3)

from sklearn.model_selection import train_test_split
X = data.drop('Yearly Amount Spent',axis=1)
y = data['Yearly Amount Spent']
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.2, random_state=13)
# 네개의 컬럼 모두를 변수로 보고 회귀
lm = sm.OLS(y_train,X_train).fit()
lm.summary()
| Dep. Variable: | Yearly Amount Spent | R-squared (uncentered): | 0.998 |
|---|---|---|---|
| Model: | OLS | Adj. R-squared (uncentered): | 0.998 |
| Method: | Least Squares | F-statistic: | 4.884e+04 |
| Date: | Tue, 17 Jan 2023 | Prob (F-statistic): | 0.00 |
| Time: | 15:48:30 | Log-Likelihood: | -1816.5 |
| No. Observations: | 400 | AIC: | 3641. |
| Df Residuals: | 396 | BIC: | 3657. |
| Df Model: | 4 | ||
| Covariance Type: | nonrobust |
| coef | std err | t | P>|t| | [0.025 | 0.975] | |
|---|---|---|---|---|---|---|
| Avg. Session Length | 12.0166 | 0.832 | 14.440 | 0.000 | 10.381 | 13.653 |
| Time on App | 35.2145 | 1.129 | 31.197 | 0.000 | 32.995 | 37.434 |
| Time on Website | -14.4797 | 0.774 | -18.715 | 0.000 | -16.001 | -12.959 |
| Length of Membership | 60.7148 | 1.151 | 52.742 | 0.000 | 58.452 | 62.978 |
| Omnibus: | 0.449 | Durbin-Watson: | 2.036 |
|---|---|---|---|
| Prob(Omnibus): | 0.799 | Jarque-Bera (JB): | 0.571 |
| Skew: | -0.038 | Prob(JB): | 0.752 |
| Kurtosis: | 2.832 | Cond. No. | 54.7 |
# 참 값, 예측 값
pred = lm.predict(X_test)
sns.scatterplot(x=y_test,y=pred)
plt.plot([min(y_test),max(y_test)], [min(y_test), max(y_test)],'r',ls='dashed',lw=3);
