前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Day05| 第四期-电商数据分析

Day05| 第四期-电商数据分析

作者头像
DataScience
发布2020-07-14 16:00:46
1.8K0
发布2020-07-14 16:00:46
举报
文章被收录于专栏:A2DataA2Data

01 前言

疫情期间,想必我们会增加网上购物,人们的生活越来越数字化。当我们消费时,无论是线上和线下都会产生大量的交易数据,对于商家来说数字化的运营方式非常必要,从大量的交易数据中进行分析得出结论以指导业务。

今天的案例是电商的订单记录分析,挖掘出订单量和产品种类,价格,以及下单时间的特点。电商分析的重点是将我们在积分落户分析中学到的分析方法和应用商店App分析的数据清洗的思路有机结合的一个案例,也是对之前知识点的加强。

获取数据, 公号回复:DT18

02 数据观察

可以用文本编辑器,打开数据观察一下。

数据集是一份电商交易订单的数据,简要说明,price价格的单位是分,35000分是350元,payMoney是支付价格,支付价格和价格会由于促销折扣存在偏差;channelid 渠道,如淘宝、京东或微店;deviceType 设备的类型,如手机,平板和电脑,后两列是订单创建时间和支付时间。

在分析开始前我们要对数据进行检查,查看是否需要清洗,这次案例出现的图表比较多,个别表格会省略,可自行在编辑器中查看。

03 数据清洗

代码语言:javascript
复制
import pandas as pd 
import numpy as np

# 加载数据,id列为索引
df = pd.read_csv('./order_info_2016.csv', index_col='id')
df.head()
代码语言:javascript
复制
df.dtypes
代码语言:javascript
复制
orderId        int64
userId         int64
productId      int64
cityId         int64
price          int64
payMoney       int64
channelId     object
deviceType     int64
createTime    object
payTime       object
dtype: object
代码语言:javascript
复制
#观察数据是否需要清洗
df.describe() # 数值型数据,数据格式正确
# 接下来一列一列分析
代码语言:javascript
复制
# id 列
df.orderId.unique().size 
代码语言:javascript
复制
104530
代码语言:javascript
复制
df.orderId.size
# 104520 少于 104557 说明有重复值,先不进行去重
代码语言:javascript
复制
104557
代码语言:javascript
复制
# userid 列
df.orderId.unique().size # 与描述统计中的userid列的count信息存在差异,也有重复值,
# 根据行数发现与order id的非重复列数相同,因此重复的行与id行相同
代码语言:javascript
复制
104530
代码语言:javascript
复制
# productId
# productId最小值是0,先来看下值为0的记录数量
df.productId[(df.productId == 0)].size
# 177行,行数较多先不处理,
# 数据清洗可以先修改异常值,如果几行数据直接删除
# 如果要删除较多数据,最好是在所有列检查完毕再删除
代码语言:javascript
复制
177
代码语言:javascript
复制
# cityid 列
df.cityId.unique().size # 城市可以有重复值
代码语言:javascript
复制
331
代码语言:javascript
复制
# price 列
# 观察最大最小值,数据和数量级正常,需要将单元分转换成元
df.price = df.price/100
代码语言:javascript
复制
# payMoney列
# 最小值为负数,取出负值行的数据的分析
df[df.payMoney < 0]
# payMoney与price没有联系,一般来说不会是负数,直接将负值删除df.drop(index=df[df.payMoney < 0].index, inplace=True)
代码语言:javascript
复制
df[df.payMoney < 0] # 再次检查,payMoney没有负值

# Type 列

代码语言:javascript
复制
# 数据分布的区间也是正常的,没有问题。
代码语言:javascript
复制
# 清洗字符串型数据
# channelid 列
# 检查是否有Null值
# 实际工作中,根据已有的chanellid可以去检查是否有不存在的channelid
df[df.channelId.isnull()]
代码语言:javascript
复制
# 去掉channelid是NaN的记录
df.drop(index=df[df.channelId.isnull()].index, inplace=True)
# 再次查看
df[df.channelId.isnull()]
代码语言:javascript
复制
# createtime 列
# datetime格式,需要确保日期和时间发生在2016年
# payTime 列 付时间,滞后可能有2017年的数据
# 对两个时间列,先转换成pandas对象,以读取索引的方式对数据进行处理
df.createTime = pd.to_datetime(df.createTime)
df.payTime = pd.to_datetime(df.payTime)
代码语言:javascript
复制
import datetime
import matplotlib.pyplot as plt 
startTime = datetime.datetime(2016, 1, 1)
endTime = datetime.datetime(2016, 12, 31, 23, 59, 59)
代码语言:javascript
复制
# 有16年之前的数据,需要删掉
df[df.createTime < startTime]
代码语言:javascript
复制
df.drop(index=df[df.createTime < startTime].index, inplace=True)
df[df.createTime < startTime]
代码语言:javascript
复制
# payTime早于createTime的也需要删掉
df.drop(index=df[df.createTime > df.payTime].index, inplace=True)
代码语言:javascript
复制
# 处理16年之后的数据
df[df.createTime > endTime] # 为空
代码语言:javascript
复制
# 看下支付时间有没有16年以前的
df[df.payTime < startTime] # 为空
代码语言:javascript
复制
# 看下支付时间在16年以后的,为空,支付时间不用处理
df[df.payTime > endTime]
代码语言:javascript
复制
# 回到最开始,orderid存在重复值,所有列检查后,进行去重
df.drop(index=df[df.orderId.duplicated()].index, inplace=True)
代码语言:javascript
复制
104520
代码语言:javascript
复制
# productid 列 存在177行为0,删除
df.drop(index=df[df.productId==0].index, inplace=True)
df.describe() # count 行保持一致,每一列的数据分布处在合理区间
# 数据清洗完毕
# 业务分析中一般数据清洗和转换会占用很多时间
# 某些工作中,数据的缺失还需要去系统中查数据填补上去,需要保持耐心~

04 数据分析

数据分析按照选取一列作为维度,可以附加其他列作为指标。

代码语言:javascript
复制
# 按照商品 productId
# 先看下商品销量的前十和后十个
productId_orderCount = df.groupby('productId').count()['orderId'].sort_values(ascending=False)
print(productId_orderCount.head(10))
print(productId_orderCount.tail(10))
代码语言:javascript
复制
productId
895    354
762    350
103    334
587    303
385    302
60     301
38     301
403    297
345    292
823    289
Name: orderId, dtype: int64
productId
948     29
856     28
621     27
272     26
563     24
347     21
597     19
468     18
986     16
1000    13
Name: orderId, dtype: int64
代码语言:javascript
复制
# 分析销售额前十商品
代码语言:javascript
复制
# 下面的分析,我在这里不显示运行结果,以节省空间,可以去掉注释后一行一行运行
# 1.对product进行分组,以orderId的数量作为指标,得出每种产品的下单数
# df.groupby('productId').count()['orderId']

# 2.对每种产品的下单数进行排序
# df.groupby('productId').count()['orderId'].sort_values(ascending=False)

# 3.还可以查看每种产品的销售额,sum求和销售额并排序
# df.groupby('productId').sum()['payMoney'].sort_values(ascending=False)
代码语言:javascript
复制
# 我们分析了销售额和销量(下单数),可以将前几排名的产品写在报告中
# 同时我们可以探究销量最差和销售额最低的商品定为问题商品,进而找到商品分析原因,是否需要优化或者将产品下架

# 销售额
productId_turnover = df.groupby('productId').sum()['payMoney'].sort_values(ascending=False)
print(productId_turnover.tail(10))
# 销量(下单数)
productId_orderCount = df.groupby('productId').count()['orderId'].sort_values(ascending=False)
代码语言:javascript
复制
productId
385    42752210
61     36157200
103    34464120
405    33952500
720    32240510
698    32049860
345    32016220
182    29660000
383    28079000
396    26955600
Name: payMoney, dtype: int64
productId
310     2287900
847     2286900
454     2253500
817     2250900
597     2184700
408     1811100
986     1478400
964     1423800
1000    1216900
347     1207000
Name: payMoney, dtype: int64
代码语言:javascript
复制
# 查找问题产品Id:销量和销售额末尾50个的产品Id取交集 使用intersection取交集
problem_productIds = productId_turnover.tail(50).index.intersection(productId_orderCount.tail(50).index)
print(problem_productIds)
代码语言:javascript
复制
Int64Index([  14,  807,  599,  676,    7,  469,  577,  551,  318,  220,  528,
             303,  314,  359,  629,  582,  985,  218,  578,  227,  277,  145,
             855,  586,  958,   91,  856,  948,  859,  874,  806,  272,  392,
              27,  460,  436,  468,  579,  868,  137,   16,  590,  247,  569,
             242,  104,  621,  478,  310,  847,  454,  817,  597,  408,  986,
             964, 1000,  347],
           dtype='int64', name='productId')
代码语言:javascript
复制
# city列分析可以和商品维度类似,不做演示
# cityId_orderCount = df.groupby('cityId').count(['orderId'].sort_values(ascending=False)
# cityId_payMoney = df.groupby('cityId').sum(['payMoney'].sort_values(ascending=False)
代码语言:javascript
复制
# price 价格分析
# 价格是一个连续的值,需要进行区间分段分析
# 观察每个区间-价格段的销量分析,可以得知那种价格区间的商品销售最好
df.describe()
# 价格最大值是229.56,最小值是0.06元
代码语言:javascript
复制
# 按照10元的区间取分桶,
bins = np.arange(0, 250, 10)
pd.cut(df.price, bins).value_counts()
# 有一些价格段没有数据,可以发现0-10元和10-20元的产品卖的是最多的
# 价格大于100元的产品卖的很少了
代码语言:javascript
复制
(0, 10]       74757
(10, 20]      18303
(20, 30]       7123
(30, 40]       2589
(40, 50]        913
(50, 60]        341
(60, 70]        174
(70, 80]         58
(80, 90]         30
(90, 100]        24
(100, 110]       13
(110, 120]        4
(130, 140]        4
(220, 230]        2
(120, 130]        1
(180, 190]        1
(140, 150]        0
(150, 160]        0
(160, 170]        0
(170, 180]        0
(190, 200]        0
(200, 210]        0
(210, 220]        0
(230, 240]        0
Name: price, dtype: int64
代码语言:javascript
复制
# 直方图
# 觉得尺寸小的话可以先设置下
# plt.figure(figsize=(16, 16))
plt.hist(df['price'], bins)
# 可以看到做出来的图不是很好看和精细,
# 那么为了更快的出图,可以将数据保存下来,导入excel
# 或者Tableau,PowerBI中进行可视化
代码语言:javascript
复制
# channelId
# 渠道的分析类似于productId,可以得出成交量最多的渠道,订单数最多的渠道来自天猫还是京东
# 渠道很多时候是需要花钱买流量的,所以还需要根据渠道的盈利情况和渠道成本进行综合比较,
# 同时也可以渠道和商品等多个维度综合分析,看看不同渠道的卖的最好的商品是否相同
代码语言:javascript
复制
# 下单时间分析
# 按小时的下单量分布,在下单时间多的时间段做推广
# 中午12, 13, 14点下单比较多,应该是午休的时候,然后是晚上20点左右
# 晚上20点左右几乎是所有互联网产品的一个高峰,对于电商互联网企业,下单高峰要注意网站的稳定性、可用性
df['orderHour'] = df.createTime.dt.hour
df.groupby('orderHour').count()['orderId'].plot()
代码语言:javascript
复制
# 按照星期来看,周六下单最多,其次是周四周五
df['orderWeek'] = df.createTime.dt.dayofweek
df.groupby('orderWeek').count()['orderId']
代码语言:javascript
复制
orderWeek
0    12503
1    12489
2    12933
3    13794
4    16200
5    19496
6    16922
Name: orderId, dtype: int64
代码语言:javascript
复制
# 下单后多久支付

def get_seconds(x):
    return x.total_seconds()

df['payDelta'] = (df['payTime'] - df['createTime']).apply(get_seconds)

bins = [0, 50, 100, 1000, 10000, 100000]
pd.cut(df.payDelta, bins).value_counts()
代码语言:javascript
复制
(0, 50]            79235
(100, 1000]        12899
(50, 100]          10675
(1000, 10000]        969
(10000, 100000]      231
Name: payDelta, dtype: int64
代码语言:javascript
复制
# 饼图
# 绝大部分都在50s之内支付完成,说明用户基本很少犹豫,购买的目的性很强
pd.cut(df.payDelta, bins).value_counts().plot(kind='pie', autopct='%d%%', figsize=(10, 10))
代码语言:javascript
复制
# 月成交额
# 先把创建订单的时间设置为索引
df.set_index('createTime', inplace=True)
# resample() 对时间索引的频率进行转换
turnover = df.resample('M').sum()['payMoney']
order_count = df.resample('M').count()['orderId']

turnover.plot()
代码语言:javascript
复制
# 月下单量
order_count.plot()

05 写在后面

电商交易数据是对前几个案例学习的总结和加强版,我们要想熟练掌握Python数据分析,还是需要多动手练习。分析数据可以从两方面开始考虑,一个是维度,一个是指标,维度可以看做x轴,指标可以看成是y轴,同一个也维度可以分析多个指标。

数据清洗的策略是按列进行分析是否有重复值,异常值和缺失值,如果只有几行重复值和异常值,在数据量较大时可以直接删除。清洗的一个技巧是“重复数据后删除”,如果前几列的数据出现几十上百行重复或者有多行值为0,空值,这可能并不是真的重复或异常,而是有一行数据前几列重复后几列不同,因而不要盲目的将重复的数据删除,所有列都清洗后,再进行删除。

完成今天的学习之后,四个案例都学习完了,恭喜!如果前几天的学习没有打卡还可以补,周日晚12点截止打卡,下周举行结营仪,发放证书~

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-07-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 DataScience 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档