数据分析项目-小红书销售额预测(Python回归模型)
一、背景
小红书,是目前非常热门的电商平台。和其他电商平台不同,小红书是从社区起家。在小红书社区,用户通过文字、图片、视频笔记的分享,记录了这个时代年轻人的正能量和美好生活。
小红书通过机器学习对海量信息和人进行精准、高效匹配,已累积海量的海外购物数据,分析出最受欢迎的商品及全球购物趋势,并在此基础上把全世界的好东西,以最短的路径、最简洁的方式提供给用户。
本次的任务是协助小红书分析不同的业务决策所带来的销售额变化。
二、界定业务问题
- 预测用户的消费金额变化
- 找到对用户消费影响较大的因素
三、数据收集与评估
#调包
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
%matplotlib inline
#忽略报错
import warnings
warnings.filterwarnings("ignore")
plt.rcParams['font.sans-serif']=['Simhei']#显示中文
plt.rcParams['axes.unicode_minus']=False#显示负号
#读取数据
df=pd.read_csv("小红书数据.csv")
四、数据概况分析
df.info()
#查看缺失值
np.sum(df.isnull(),axis=0)
df.describe()
df.head(10)
小结 :
- 共有8个字段,29452条数据;
- gender,engaged_last_30数据类型错误,需转为str;;
- gender、age、engaged_last_30存在缺失值,缺失率达到40%;
- age、engaged_last_30可使用0、均值、中位数填充;
- gender用unknown填充,再转化为哑变量;
- revenue和previous_order_amount存在极端值。
五、单变量分析
- revenue
df.revenue.plot(kind='hist')
存在极端值
#查看<2000销售额分布
df[df.revenue<2000]['revenue'].plot(kind='hist')
#查看<500销售额分布
df[df.revenue<500]['revenue'].plot(kind='hist')
df[df.revenue<200].shape
(15589, 8)
df[df.revenue<500].shape
(22218, 8)
- 53%的销售额分布在2000以下;
- 75%的销售额分布在500以下。
【判断离群值】
一般的,我们认定超过75%分位数 1.5倍的四分位差的数值为离群值。
四分位差: 75%分位数 - 25%分位数
sns.boxplot(y='revenue',data=df)
df.revenue.describe()
df.revenue.describe()['25%']
74.97
df.revenue.describe()['75%']
498.7725
diff=df.revenue.describe()['75%']-df.revenue.describe()['25%']
new_max=df.revenue.describe()['75%']+1.5*diff
new_max
1134.47625
df[df.revenue<1135].shape
(27286, 8)
存在7.35%的离群值
- 清洗>1135的离群值
df1 = df[df.revenue<=1135]
df1.revenue.describe()
经过清洗离群值后,购买金额75%分布在400元以下
- gender
df1.gender.value_counts(dropna=False)#dropna=False查看NA的数据
df1.gender.value_counts(dropna=False).plot(kind='bar')
- age
df1['age'].plot(kind='hist',bins=100)
engaged_last_30
df1.engaged_last_30.value_counts(dropna=False)
- lifecycle
df1['lifecycle'].value_counts().plot(kind='bar')
- days_since_last_order
df1[' days_since_last_order '].plot(kind='hist')
- previous_order_amount
- 3rd_party_stores
df1['3rd_party_stores'].value_counts().plot(kind='bar')
六、相关与可视化
a=df1.corr()[['revenue']].sort_values('revenue',ascending=False)
a
sns.heatmap(a)
sns.regplot(x='previous_order_amount',y='revenue',data=df1)
sns.regplot(x=' days_since_last_order ',y='revenue',data=df1)
sns.barplot(x='engaged_last_30',y='revenue',data=df1)
sns.barplot(x='engaged_last_30',y='revenue',estimator=sum,data=df1)
sns.barplot(x='gender',y='revenue',data=df1)
sns.barplot(x='gender',y='revenue',estimator=sum,data=df1)
sns.regplot(x='age',y='revenue',data=df1)
sns.barplot(x='3rd_party_stores',y='revenue',data=df1)
sns.barplot(x='3rd_party_stores',y='revenue',estimator=sum,data=df1)
- 对销售额影响因素最大的以往累积购买金额;
- previous_order_amount、 days_since_last_order数值跨度很大;
- 性别为女销售额明显高;
- 只在自营产品购买的销售额明显高。
七、回归模型建立
1、数据处理
df2=df1.copy()
#缺失值处理 :gender-unknown填充
df2['gender']=df2['gender'].fillna('unknown')
#缺失值处理 :age-o填充
df2['age']=df2['age'].fillna(0)
#缺失值处理 :engaged_last_30-0填充
df2['engaged_last_30']=df2['engaged_last_30'].fillna(0)
#转换数据类型
df2['gender']=df2['gender'].astype(str)
df2['engaged_last_30']=df2['engaged_last_30'].astype(str)
df2=pd.get_dummies(df2)
df2.info()
2、模型建立
#调包
from sklearn import datasets
#调取线性回归包工具
from sklearn.linear_model import LinearRegression
model=LinearRegression()
#设置自变量和因变量 ,本次先设previous_order_amount、days_since_last_order为自变量
x=df2[['previous_order_amount',' days_since_last_order ']]
y=df2['revenue']
model.fit(x,y)
#查看斜率
model.coef_
#查看截距
model.intercept_
array([0.01841742, 5.00650081])
189.26109618921646
y=0.018 * previous_order_amount+5.0065 * days_since_last_order+189.26
3、模型评估
#计算y预测值
predictions=model.predict(x)
#计算误差
error=y-predictions
#计算mae
mae=abs(error).mean()
#计算rmse
rmse=(error**2).mean()**.5
#输出mae、rmse
print(mae)
print(rmse)
208.25098860671116
263.2688258746202
八、回归模型优化
1、模型优化
- 改变缺失值填充方式,age、engaged_last_30均值填充
- 增加X变量 X=previous_order_amount、days_since_last_order、engaged_last_30、gender或者除revenue的所有列
#缺失值处理 :age、engaged_last_30-均值填充
df3=df1.copy()
df3['gender']=df3['gender'].fillna('unknown')
df3['age']=df3['age'].fillna(df3['age'].mean())
df3['engaged_last_30']=df3['engaged_last_30'].fillna(df3['engaged_last_30'].mean())
#更改数据类型
df3['gender']=df3['gender'].astype(str)
df3['engaged_last_30']=df3['engaged_last_30'].astype(str)
#生成哑变量
df3=pd.get_dummies(df3)
df3.info()
#设置自变量和因变量 ,本次先设previous_order_amount、days_since_last_order为自变量
x=df3[['previous_order_amount',' days_since_last_order ','engaged_last_30_0.0','engaged_last_30_1.0','engaged_last_30_0.0698705875205055','gender_0.0','gender_1.0','gender_unknown']]
y=df3['revenue']
model.fit(x,y)
#查看斜率
model.coef_
#查看截距
model.intercept_
array([ 1.80980666e-02, 4.90543842e+00, -2.38038702e+01, 2.68323878e+01, -3.02851755e+00, 1.03894426e+00, 1.98957329e+00, -3.02851755e+00])
204.57579835360295
#计算y预测值
predictions=model.predict(x)
#计算误差
error=y-predictions
#计算mae
mae=abs(error).mean()
#计算rmse
rmse=(error**2).mean()**.5
#输出mae、rmse
print(mae)
print(rmse)
207.88316933247887
263.00322131497086
进一步优化 ,X为除revenue的所有列
#模型的评估,x为除revenue列的所有列
x=df3.drop('revenue',axis=1)
y=df3['revenue']
model.fit(x,y)
predictions=model.predict(x)#计算y预测值
error=predictions-y#计算误差
rmse=(error**2).mean()**.5#计算rmse
mae=abs(error).mean()#计算mae
print(mae)
print(rmse)
206.8590215207069
262.14209518606816
2、标准模型输出表
from statsmodels.formula.api import ols
# x为除revenue列的所有列