分类变量:性别、民族、居住城市、是否违约、(等级变量:教育、学历、客户满意度、年龄段)
连续性变量:年龄,收入
总体:对客观事物研究时,总体是包含所有研究个体的集合,比如研究中国人的身高,那么所有中国人的身高就是总体,某一个中国人的身高就是个体。
样本:在总体里面抽样,经过抽样总体中的部分个体,就形成了样本,样本是总体的子集。
统计量:均值、标准差、中位数、分位数、众数。
离散程度(反应数据某些趋势):极差、四分位差、方差、变异系数。
import numpy as np
import pandas as pd
from scipy import stats
import os
os.chdir('/Users/songdi/Desktop/code/python')
data=pd.read_excel('trade.xlsx',encoding='utf-8')
data['sales'].mean() #均值
data['sales'].std() #标准差
data['sales'].median() #中位数
data['sales'].quantile([0,0.05,0.25,0.5,0.75]) #分位数
data['sales'].mode() #众数
data['sales'].mode()[1] #众数不止一个时可以取出某个
data['region'].value_counts() #分类变量
data['sales'].max()-data['sales'].min() #极差
data['sales'].quantile(0.75)-data['sales'].quantile(0.25) #四分位差
cv=data['sales'].std()/data['sales'].mean() #变异系数
点估计:用样本统计量去估计总体参数。(估计出一个值)
区间估计:区间估计用一个包括有真实值的区间范围来估计参数的取值范围。(估计出一个范围)
置信度和置信区间:样本均值包含在(1-a)%范围之内,a%的区间未包含均值。
样本均值近似正态分布:若样本数量足够大,产生的均值是近似符合正态分布的。
#点估计
data['sales'].mean() #均值
#区间估计 (中心极限定理)
n=len(data['sales']) #样本数量
se=stats.sem(data['sales']) #计算样本均值标准物,即data['sales'].std()/np.sqrt(n)
interval=stats.norm.interval(0.95,data['sales'].mean(),se) #求区间估计,即data['sales'].mean()-1.96*se到data['sales'].mean()+1.96*se
(1)提出原假设和备择假设
(2)确定适当的检验统计量
(3)规定显著性水平
(4)计算检验统计量的值
(5)做出决策
import statsmodels.api as sm
#t检验
d1=sm.stats.DescrStatsW(data['sales'])
d1.ttest_mean(data['sales'].mean()) #t统计量,概率,自由度个数(即样本量-1)
#双样本t检验
data.groupby('region').mean()['sales']
region0=data[data['region']=='华北']['sales']
region1=data[data['region']=='华南']['sales']
leveneTestRes=stats.levene(region0,region1) #方差齐性检验
stats.stats.ttest_ind(region0,region1,equal_var=True)
卡方检验主要用于分析两个分类变量之间的关系。(例:男女之间的教育水平是否有显著性差异)
方差分析用于分析多于两个分类的离散型变量与连续变量的关系。
#卡方检验
cross_table=pd.crosstab(data.trans_cost,data.sales,margins=True)
from scipy import stats
stats.chi2_contingency(cross_table) #显著性水平
pd.crosstab(data.trans_cost,data.sales,normalize='index')
#方差分析
from statsmodels.stats.anova import anova_lm
from statsmodels.formula.api import ols
model=ols('sales ~ C(region)',data=data.dropna()).fit()
anova_lm(model) #显著性水平
Pearson相关系数:衡量两变量线性相关关系。
Spearman相关系数:对于有序变量而言,用Spearman更加准确一点。
Kendall相关系数:用于衡量两个变量的非线性关系。
import matplotlib.pyplot as plt
plt.scatter(x=data.trans_cost,y=data.sales,c='steelblue')
plt.show()
coor_pear=data[['trans_cost','sales']].corr(method='pearson') #Pearson相关系数
coor_pear.loc['trans_cost','sales']
coor_spearman=data[['trans_cost','sales']].corr(method='spearman') #Spearman相关系数
coor_kendall=data[['trans_cost','sales']].corr(method='kendall') #Kendall相关系数
data['sales_1']=data['sales'].rank() #秩
data['trans_1']=data['trans_cost'].rank()
data[['sales','sales_1']]
coor_pear=data[['trans_cost','sales']].corr(method='pearson')
coor_pear.loc['trans_cost','sales']
import os
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import plotly as py
import plotly.graph_objs as go
py.offline.init_notebook_mode()
pyplot=py.offline.iplot
import seaborn as sns
sns.set(style='darkgrid',context='notebook',font_scale=1.2)
import warnings
warnings.filterwarnings('ignore')
# 1.读取数据
os.chdir(r'/Users/songdi/Desktop/code/python/data')
online_data=pd.read_csv('data.csv',encoding='ISO-8859-1',dtype={'CustomerID':str})
# 2.理解数据:理解数据每一列的含义、类型
online_data.head(5)
online_data.info()
online_data[online_data['InvoiceNo'].str[0]=='C'] #订单编号开头为C的代表退货
# 3.数据清洗
online_data.apply(lambda x:sum(x.isnull())/len(x),axis=0) #计算每列的缺失率(缺失值/长度)
df1=online_data.dropna(how='any').copy() #删除数据缺失的行
df1['InvoiceDate']=pd.to_datetime(df1['InvoiceDate'],errors='coerce') #转换为日期时间格式
df1['InvoiceDate']=df1['InvoiceDate'].dt.date #只保留日期部分,此时会变为字符串格式
df1['InvoiceDate']=pd.to_datetime(df1['InvoiceDate'],errors='coerce') #再转化为日期格式
df1['Price']=df1.apply(lambda x:x[3]*x[5],axis=1) #算出客户消费金额
# 4.数据分析和可视化
#问题一:购买商品数前十的国家是哪些?
quantity_first_10=df1[df1['Quantity']>0].groupby('Country').sum()['Quantity']. sort_values(ascending=False).head(10) #分组统计
trace_basic=[go.Bar(x=quantity_first_10.index.tolist(), y=quantity_first_10.values. tolist(), marker=dict(color='orange'), opacity=0.5)] #数据
layout=go.Layout(title='购买商品前10的国家',xaxis=dict(title='国家')) #布局
figure_basic=go.Figure(data=trace_basic,layout=layout)
pyplot(figure_basic)
#问题二:交易额前十的国家是哪些?
price_first_10=df1[df1['Quantity']>0].groupby('Country').sum()['Price']. sort_values(ascending=False).head(10) #分组统计
trace_basic=[go.Bar(x=price_first_10.index.tolist(), y=price_first_10.values.tolist(), marker=dict(color='orange'),opacity=0.5)] #数据
layout=go.Layout(title='交易额前10的国家',xaxis=dict(title='国家')) #布局
figure_basic=go.Figure(data=trace_basic,layout=layout)
pyplot(figure_basic)
#问题三:哪些月份销量较佳?
df1['month']=df1['InvoiceDate'].dt.month #添加月份列
df1[df1['Quantity']>0].groupby('month').sum()['Quantity'].sort_values(ascending=False). plot(kind='bar') #用seaborn绘图展示每月销量数据
plt.xticks(rotation=45)
#问题四:客单价等于多少?(用户每次交易平均消费金额)
len(df1['InvoiceNo'].drop_duplicates()) #订单号有重复值,但是暂时不考虑
sumPrice=df1[df1['Quantity']>0]['Price'].sum() #交易总价
count_ID=df1[df1['Quantity']>0]['InvoiceNo'].count() #交易次数
avgPrice=sumPrice/count_ID
#问题五:分析用户购物行为?
customer=df1[df1['Quantity']>0].groupby('CustomerID').agg({'InvoiceNo':'nunique','Quantity':np.sum,'Price':np.sum}) #按不同客户进行聚合计算
customer.describe() #进行描述性统计计算
# 5.结论和建议
(1) 用户平均消费4次,有的客户甚至消费高达210次,是产品的忠实客户。
(2) 用户平均消费金额为2053元,而75%的用户消费金额只有1661,可见有些用户消费金额较大,属于非常有价值的用户,需要重点保持关注。
(3) 用户购买产品数量平均高达1194件,由于销售对象主要是批发商,算是正常的数量。
RFM模型(用户分类)
对比分析不同用户群体在时间、地区等维度下交易量、交易金额指标,并根据分析结果提出优化建议。
R:最近一次消费时间(最近一次消费到参考时间的长度)
F:消费的频次(单位时间内消费了多少次)
M:消费的金额(单位时间内总消费金额)
# 1.读取数据
df=pd.read_csv('data.csv',encoding='ISO-8859-1',dtype={'CustomerID':str})
# 2.理解数据
df.shape
df.info()
# 3.数据清洗
df.apply(lambda x:sum(x.isnull())/len(x),axis=0) #统计各列缺失率
df.drop(['Description'],axis=1,inplace=True) #删除无用列
df['CustomerID']=df['CustomerID'].fillna('U') #把缺失值赋值为U
df['amount']=df['Quantity']*df['UnitPrice'] #算出客户消费金额
df['date']=[x.split(' ')[0] for x in df['InvoiceDate']] #拆分出订单时间中的日期
df['time']=[x.split(' ')[1] for x in df['InvoiceDate']] #拆分出订单时间中的时间
df.drop(['InvoiceDate'],axis=1,inplace=True) #删除无用列
df['year']=[x.split('/')[2] for x in df['date']] #拆分出订单日期中的年
df['month']=[x.split('/')[0] for x in df['date']] #拆分出订单日期中的月
df['day']=[x.split('/')[1] for x in df['date']] #拆分出订单日期中的日
df['date']=pd.to_datetime(df['date']) #把订单日期转换为日期格式
df=df.drop_duplicates() #删除重复值
df.describe() #进行描述性统计计算,查找异常数据
df2=df.loc[df['UnitPrice']<=0]
df2.shape[0]/df.shape[0] #计算异常值比例
df2['UnitPrice'].groupby(df2['UnitPrice']).count() #查看异常值特点
# 4.数据分析和可视化
#问题一:退货率
df1=df.loc[df['Quantity']<=0]
tt=pd.pivot_table(df1,index=['year'],columns=['month'],values=['amount'],aggfunc={'amount':np.sum}) #透视图
df2=df[(df['Quantity']>0)&(df['UnitPrice']>0)]
pp=pd.pivot_table(df2,index=['year'],columns=['month'],values=['amount'],aggfunc={'amount':np.sum}) #透视图
np.abs(tt/pp) #退货率透视图
np.abs(tt/pp).loc['2011'].mean() #查看2011年每月的平均退货率
#问题二:用户分类(RFM模型)
R_value=df2.groupby('CustomerID')['date'].max() #求客户的最新购买日期
R_value=(df2['date'].max()-R_value).dt.days #求客户最近一次消费到参考时间的长度
F_value=df2.groupby('CustomerID')['InvoiceNo'].nunique() #计算每个客户购物订单数
M_value=df2.groupby('CustomerID')['amount'].sum() #计算每个客户消费总金额
R_value.describe()
plt.hist(R_value,bins=30)
plt.show()
F_value.describe()
plt.hist(F_value[F_value<20],bins=30)
plt.show()
M_value.describe() #判断数据是否异常,看均值和五十分位数差异大不大
plt.hist(M_value[M_value<2000],bins=30)
plt.show()
#离散化处理
F_value.quantile([0.1,0.2,0.3,0.4,0.5,0.9,1])
R_bins=[0,30,90,180,360,720]
F_bins=[1,2,5,10,20,5000]
M_bins=[0,500,2000,5000,10000,200000]
R_score=pd.cut(R_value,R_bins,labels=[5,4,3,2,1],right=False) #R值越小越好
F_score=pd.cut(F_value,F_bins,labels=[1,2,3,4,5],right=False) #F值越大越好
M_score=pd.cut(M_value,M_bins,labels=[1,2,3,4,5],right=False) #M值越大越好
rfm=pd.concat([R_score,F_score,M_score],axis=1)
rfm.rename(columns={'date':'R_score','InvoiceNo':'F_score','amount':'M_score'}, inplace=True)
rfm.info()
for i in ['R_score','F_score','M_score']:
rfm[i]=rfm[i].astype(float)
rfm.describe()
#对客户做分层处理
rfm['R']=np.where(rfm['R_score']>3.82,'高','低')
rfm['F']=np.where(rfm['F_score']>2.03,'高','低')
rfm['M']=np.where(rfm['M_score']>1.89,'高','低')
rfm['value']=rfm['R'].str[:]+rfm['F'].str[:]+rfm['M'].str[:]
def trans_value(x):
if x=='高高高':
return '重要价值客户'
elif x=='高低高':
return '重要发展客户'
elif x=='低高高':
return '重要保持客户'
elif x=='低低高':
return '重要挽留客户'
elif x=='高高低':
return '一般价值客户'
elif x=='高低低':
return '一般发展客户'
elif x=='低高低':
return '一般保持客户'
else:
return '一般挽留客户'
rfm['level']=rfm['value'].apply(trans_value)
rfm['level'].value_counts()
trace_basic=[go.Bar(x=rfm['level'].value_counts().index, y=rfm['level'].value_counts().values, marker=dict(color='orange'), opacity=0.5)]
layout=go.Layout(title='用户等级情况',xaxis=dict(title='用户重要度'))
figure_basic=go.Figure(data=trace_basic,layout=layout)
pyplot(figure_basic)
trace=[go.Pie(labels=rfm['level'].value_counts().index, values=rfm['level'].value_counts().values, textfont=dict(size=12,color='white'))]
layouts=go.Layout(title='用户等级比例')
figure=go.Figure(data=trace,layout=layouts)
pyplot(figure)
# 5.结论和建议
(1)退货率2011年11月、12月偏高。
(2)公司的主要目标客户是重要发展客户和重要价值客户。