数据
2020年5月25日京东大家电-家用电器-冰箱订单数据,按10%抽样,约22MB(70k+条数据)
包含信息:
user_log_acct --用户账号
parent_sale_ord_id --父订单号
sale_ord_id --订单号
sale_ord_tm --订单时间
sale_ord_dt --订单日期
item_sku_id --商品sku
item_name --商品名称
brandname --品牌名称
sale_qtty --商品数量
item_first_cate_name --一级品类名称
item_second_cate_name --二级品类名称
item_third_cate_name --一级品类名称
before_prefr_unit_price --优惠前单价
after_prefr_unit_price --优惠后单价
user_actual_pay_amount --实际支付价格
sale_ord_valid_flag --订单有效标志
cancel_flag --订单取消标志
check_account_tm --支付时间
total_offer_amount --总优惠金额
self_ord_flag --自营标志
user_site_city_id --用户所在城市编号
user_site_province_id–用户所在省份编号
user_lv_cd --用户会员等级
数据预处理
缺失值处理
用户城市和省份信息有部分缺失,猜测原因是部分用户隐藏了IP地址,不影响分析,可以用‘缺失值’代替
部分订单的订单时间是空值,原因是订单尚未支付,不影响分析,可以将其赋特殊值比如-1或者不处理
数据逻辑错误
有用户的城市ID为-1只有1个,影响不大可以删除
优惠前冰箱的最低价格为288,数据中存在大量的低价订单,其中绝大部分是保修、返现等无价值订单,一小部分是异常订单,可以忽略,只筛选出优惠前价格大于500的数据
import pandas as pd
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
import seaborn as sns
from scipy import stats
from matplotlib.ticker import FuncFormatter
plt.rcParams['font.sans-serif'] = ['KaiTi', 'SimHei', 'FangSong']
df=pd.read_csv('course_order_d.csv',sep='\t')
df.head()
#查看列名
df.columns
df.info()
#数据清洗
#数据类型转换
#缺失值和异常值处理
#优惠前冰箱的最低价格为288元,低于此价格的订单认为是异常订单 (df['before_prefr_unit_price']<288).sum() 为14252个
#用户的城市ID为-1删除,只有1个
df=df[(df['before_prefr_unit_price']>=288) & (df['user_site_city_id']!=-1)]
df.shape #(62378, 23)
#查看重复订单数量
print(df["sale_ord_id"].duplicated().sum()) #843
#去掉订单号重复的数据(这里京东的建议保留第一个)
df.drop_duplicates(subset=['sale_ord_id'],keep='first',inplace=True)
df.info()
城市、省份信息缺失,订单时间缺失部分订单的订单时间是空值,原因是订单尚未支付,可以将其赋特殊值比如Not Given
df.user_site_city_id.fillna('Not Given',inplace = True)
df.user_site_province_id.fillna('Not Given',inplace = True)
df.check_account_tm.fillna('Not Given',inplace = True)
# 添加总价格列 等于 商品数量*优惠后单价
df['total_actual_pay']=df['sale_qtty']* df['after_prefr_unit_price']
df.head()
宏观分析
#取消订单数 17782
order_cancel=df[df.cancel_flag==1]['sale_ord_id'].count()
#总订单数 61535
order_num=df['sale_ord_id'].count()
#df2只包含有效订单(sale_ord_valid_flag订单有效标志为1 且 cancel_flag订单取消标志为0 )
df2=df.copy()
df2=df2[(df2['sale_ord_valid_flag']==1)&(df2['cancel_flag']==0)]
#有效订单数量 33845
order_vaild=df2['sale_ord_id'].count()
#支付订单数量 28768
order_payed=df2['sale_ord_id'][df2['user_actual_pay_amount']!=0].count()
#未支付订单数量 5077
order_unpay=df2['sale_ord_id'][df2['user_actual_pay_amount']==0].count()
#总销售额
total_sales = df2['user_actual_pay_amount'].sum()
# GMV:本实例中指所有有效订单的总交易额
GMV = df2['total_actual_pay'].sum()
#总用户数
total_users = df['user_log_acct'].nunique()
print('订单总数:',order_num)
print('取消订单数:',order_cancel)
print('有效订单总数:',order_vaild)
print('已支付订单:',order_payed)
print('总销售额:',total_sales)
print('GMV:',GMV)
print('总用户数:',total_users)
fig,axes = plt.subplots(1,2,figsize =(10,5),dpi=100)
labels1=['取消','未取消']
X=[order_cancel,order_num-order_cancel]
axes[0].pie(X,labels=labels1,autopct='%1.2f%%',colors = ['#1a445d','#6490a9'],pctdistance = 1.3,startangle = 90)
axes[0].set_title("订单总数取消情况", fontsize=25)
labels2=['支付','未支付']
Y=[order_payed,order_unpay]
axes[1].pie(Y,labels=labels2,autopct='%1.2f%%',colors = ['#1a445d','#6490a9'],pctdistance = 1.2,startangle = 90)
axes[1].set_title("有效订单数支付情况", fontsize=25)
优惠后单价累积分布图
通过整体的价格分布我们可以发现,约80%的订单在3000元以下。
price_series=df2['after_prefr_unit_price']
price_series.describe([0.25,0.5,0.7,0.75,0.8,0.85,0.9])
order_price = pd.DataFrame(df2.groupby('after_prefr_unit_price')['after_prefr_unit_price'].count())
order_price.columns = ['ord_price_qua']
order_price['price_rate_cum'] = (order_price['ord_price_qua']/(order_price['ord_price_qua'].sum())).cumsum()
fig = plt.figure(figsize=(20,8),dpi=120)
ax = fig.add_subplot(111,fc='w')
ax.tick_params(labelsize=12,colors='k') #刻度字体大小12
plt.xlabel('优惠后单价',fontdict={
'color':'k', 'size':18})
def to_percent(temp,position):
return '%1.1f'%(100*temp)+'%'
plt.gca().yaxis.set_major_formatter(FuncFormatter(to_percent))
ax.plot(order_price.index,order_price['price_rate_cum'],color='#1a445d',linewidth=1.8)
ax.set_title("优惠后单价累积分布图", fontsize=25)
# 设置有边框和头部边框颜色为空right、top、left
[ax.spines[loc_axis].set_visible(False) for loc_axis in ['top','right','left']]
plt.grid(color = "k", alpha=0.5,linewidth=0.5)
微观分析
时间维度
df3=df2.copy()
#提取小时
df3['order_time_hms']=df3['sale_ord_tm'].apply(lambda x:int(str(x).split(' ')[1][0:2]))
#每个小时订单数
pay_time_df=df3.groupby('order_time_hms')['sale_ord_id'].count()
x=pay_time_df.index
y=pay_time_df.values
fig = plt.figure(figsize=(20,8