python数据分析实战之电商交易分析
文章目录
1、明确需求和目的
- 通过以往的电商交易历史数据,分析商品销售的总体情况以及不同维度下的销售情况。
2、数据收集
- 数据集为某电商平台2016年一整年的交易数据, 数据包含104557条数据,10个字段。
- 除此之外,还有一个设备的转换说明文档。
3、数据预处理
3.1 数据整合
3.1.1 加载相关库和数据集
- 使用的库主要有:pandas、numpy、matplotlib
- 使用的数据集:某电商2016年交易情况的数据集文件和设备信息文件
# 加载数据分析需要使用的库
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# 加载交易信息数据集
df = pd.read_csv('order_info_2016.csv', index_col='id')
df.head()
# 加载设备信息
device_type = pd.read_csv('device_type.txt')
device_type
------------------------
id deviceType
0 1 PC
1 2 Android
2 3 iPhone
3 4 Wap
4 5 other
数据整合,将两个文件的信息整合在一起:
df2 = pd.DataFrame()
df2["deviceType"] = device_type["id"]
df2["deviceName"] = device_type["deviceType"]
# 整合数据集信息和设备信息
df = pd.merge(df,df2,how='left')
3.1.2 数据概览
首先看一下数据集大小(行列信息):
df.shape
--------------------- # 相比原始数据,多了一列设备名称
(104557, 11)
看一下数据概况:
# df.info()
df.describe()
3.2 数据清洗
3.2.1 缺失值处理
首先看一下缺失值情况:
df.isnull().sum(axis=0) # 查看缺失值
----------------------------------------
orderId 0
userId 0
productId 0
cityId 0
price 0
payMoney 0
channelId 8
deviceType 0
createTime 0
payTime 0
deviceName 87
dtype: int64
发现 deviceName 有87个缺失值,而 deviceType 没有缺失值,看一下 deviceType 的取值分布:
df["deviceType"].value_counts()
----------------------------------
2 52448
3 42948
1 7054
4 2017
6 87
5 3
Name: deviceType, dtype: int64
发现这一列有类别为6的值,数量刚好为87,而设备信息文件并没有6这个类别,怀疑是信息填错了,将其重新归类为5,同时将 deviceName 的缺失值用"other"进行填充:
df['deviceType'].replace({6: 5}, inplace = True)
df.fillna({"deviceName": "other"}, inplace=True)
还有一列有8个缺失值,数据占比较少,我们直接将其删除:
df.dropna(inplace=True)
df.isnull().sum(axis=0)
------------------------
orderId 0
userId 0
productId 0
cityId 0
price 0
payMoney 0
channelId 0
deviceType 0
createTime 0
payTime 0
deviceName 0
dtype: int64
删除缺失值之后,再来看一下数据集的大小:
df.shape
--------------------------
(104549, 11)
3.2.2 异常值处理
可以通过数据概况初步探索异常值:
df.describe()
根据上面的结果可以看出 productId 最小值是0,payMoney 有负值,这明显是不合理的,我们需要对其进行处理。
首先看看 productId 值为0的数量,数量较少的话直接删除:
df.productId[(df.productId == 0)].size
-------------------------------------------------
177
# 177条记录,数量不多,直接删掉
df.drop(index=df[df.productId==0].index, inplace=True)
对于 payMoney 存在负值的记录,直接将其删除:
df.productId[(df.payMoney < 0)].size
----------------------------------------
6
# 只有6条记录,直接删除
df.drop(index=df[df.payMoney < 0].index, inplace=True)
再看一下这两列值的情况:
df[["productId", "payMoney"]].describe()
------------------------------------------
productId payMoney
count 104366.000000 1.043660e+05
mean 505.417626 8.690449e+04
std 287.629531 9.075357e+04
min 1.000000 0.000000e+00
25% 255.000000 3.360000e+04
50% 508.000000 5.500000e+04
75% 759.000000 1.040000e+05
max 1000.000000 2.294200e+06
3.2.3 多余记录的删除
因为是要分析2016年的数据,所以需要去除非2016年的数据,以及付款时间小于创建时间的数据:
import datetime
# 先把createTime和payTime转换成datetime格式
df.createTime = pd.to_datetime(df.createTime)
df.payTime = pd.to_datetime(df.payTime)
startTime = datetime.datetime(2016, 1, 1)
endTime = datetime.datetime(2016, 12, 31, 23, 59, 59)
df.drop(index=df[df.createTime < startTime].index, inplace=True)
df.drop(index=df[df.createTime > endTime].index, inplace=True)
# payTime早于createTime的也需要删掉
df.drop(index=df[df.createTime > df.payTime].index, inplace=True)
3.2.4 重复值的处理
首先看一下重复的行:
print(df.duplicated().sum()) # 查看重复值的数量
---------------------------------------
0
没有重复的行,但可能存在重复的订单号,按理说订单号是唯一的,我们来检查一下:
print(df.orderId.unique().size)
print(df.orderId.size)
--------------------------------
104339
104366
订单号存在重复值,我们对重复的记录进行删除:
df.drop(index=df[df.orderId.duplicated()].index, inplace=True)
其余字段有重复值是正常的,不需要进行处理。
4、数据分析
4.1 总体情况分析
先来看一下2016年一年的总体情况:
# 总订单数,总下单用户,总销售额,有销售的商品数
print(df.orderId.count())
print(df.userId.unique().size)
print(df.payMoney.sum()/100) # 原单位是“分”,需要转换成“元”
print(df.productId.unique().size)
--------------------------------------
104329
102447
90666399.7
1000
再看看一下各个月的情况:
# 增加一个月份列,方便按照月份来进行统计
df['month'] = df["payTime"].dt.month
month = df["month"].unique()
order_count = df.groupby(by='month').count()["orderId"]
plt.bar(month, order_count)
plt.show()
从上图可以看出,各个月的订单数并不均衡,最高峰集中在5-8月份,9-12月份订单数明显下降。针对这一现象可以着重考虑如何提高9-12月份份销量。
4.2 各维度分析
- 分析数据可以从两方面开始考虑,一个是维度,一个是指标,维度可以看做x轴,指标可以看成是y轴,同一个维度可以分析多个指标,同一个维度也可以做降维升维。
(1)商品分析
看一下销量前十名的商品:
productId_count = df.groupby('productId').count()['orderId'].sort_values(ascending=False)
print(productId_count.head(10))
-------------------------------------
productId
895 354
762 350
103 334
587 303
385 302
60 301
38 301
403 297
345 292
823 288
Name: orderId, dtype: int64
销量后十名的商品:
print(productId_count.tail(10))
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
可以看出,前十名和后十名的商品销量相差很大。
再看一下销售额前十名的商品:
# 原单位是“分”,需要转换成“元”
df['payMoney'] = df['payMoney'] / 100
productId_amount = df.groupby('productId').sum()['payMoney'].sort_values(ascending=False)
print(productId_amount.head(10))
-------------------------------------------
productId
385 427522.1
61 361572.0
103 344641.2
405 339525.0
720 322405.1
345 320162.2
698 318458.6
182 296600.0
383 280790.0
396 269556.0
Name: payMoney, dtype: float64
销售额后十名的商品:
print(productId_amount.tail(10))
------------------------------------
productId
310 22879.0
847 22869.0
454 22535.0
817 22509.0
597 21847.0
408 18111.0
986 14784.0
964 14238.0
1000 12169.0
347 12070.0
Name: payMoney, dtype: float64
根据以上的结果,对销售额/销量排名前十名的商品可以采取增加库存,增加推广成本等措施来进一步提升销量。而对于销售额/销量排名后十名的商品,则需要进行调研分析,确定商品销售额低下的原因,采取一定措施进行商品销量的提升,也可以考虑适当减少这些商品的库存,以减少损失。
看下销量和销售额最后100个商品的交集,如果销量和销售额都不达标,这些商品需要看看是不是要优化或者下架:
problem_productIds = productId_amount.tail(100).index.intersection(productId_count.tail(100).index)
print(len(problem_productIds))
print(problem_productIds.tolist())
----------------------------------------
58
[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]
一共有58个商品,可能需要进一步分析优化或者下架。
(2)城市分析
城市分析和商品分析类似,可以看一下销量和销售额都很高的城市,作为重点发展城市。
看一下销量前10的城市:
cityId_Count = df.groupby('cityId').count()['orderId'].sort_values(ascending=False)
print(cityId_Count.head(10))
-------------------------------------------
cityId
110001 5490
130001 4100
60011 3639
40001 3291
220002 3051
230001 2951
240001 2753
120001 2435
220005 2168
70001 2075
Name: orderId, dtype: int64
销售额前10的城市:
cityId_amount = df.groupby('cityId').sum()['payMoney'].sort_values(ascending=False)
print(cityId_amount.head(10))
-------------------------------
cityId
110001 6127732.8
220002 4406761.8
130001 3961264.7
220005 3374686.7
60011 2787478.1
40001 2531856.7
120001 2418538.8
70001 2192634.7
230001 2176484.0
220001 1983682.4
Name: payMoney, dtype: float64
销量和销售额都排名前5的城市:
good_cityId = cityId_amount.head(5).index.intersection(cityId_Count.head(5).index)
print(len(good_cityId))
print(good_cityId.tolist())
------------------------------------
4
[110001, 220002, 130001, 60011]
一共有4个城市销量和销售额表现优秀, 因此,我们可以针对这些城市开展更多的优惠活动或者线下活动,进一步提升销量。
(3)价格分析
对于价格,可以看下所有商品价格的分布,这样可以知道什么价格的商品卖的最好:
# 原单位是“分”,需要转换成“元”
df['price'] = df['price'] / 100
# 先按照100的区间取分桶
bins = np.arange(0, 7500, 100)
print(pd.cut(df.price, bins).value_counts())
-----------------------------------------------
(400, 500] 14791
(300, 400] 10737
(200, 300] 9966
(500, 600] 9189
(600, 700] 8777
(100, 200] 7123
(700, 800] 7111
....
(6400, 6500] 2
(5500, 5600] 1
(7300, 7400] 0
Name: price, Length: 74, dtype: int64
plt.figure(figsize=(16, 16))
plt.hist(df['price'], bins)
从上面可以看出,价格在400-500之间的商品卖的最好,大部分商品价格在0-1000之间,所以可以考虑进一步增加这些价格区间的商品。
(4)设备类型分析
下单设备排名:
df.groupby('deviceName').count()['orderId'].sort_values(ascending=False)
-------------------------------------------------------------
deviceName
Android 52340
iPhone 42852
PC 7033
Wap 2014
other 90
Name: orderId, dtype: int64
从上面可以看出,安卓和苹果客户端下单数最多,和大多数人使用手机网购相符合。如果想要进一步推广,应该将重点放在安卓客户端,其次是苹果客户端。
(5)下单时间分析
- 按小时分析
# 按小时的下单量分布,可以按时间做推广
df['orderHour'] = df.createTime.dt.hour
df.groupby('orderHour').count()['orderId'].plot()
从上图可以看出, 中午12-14点下单比较多,应该是午休的时候,然后是晚上20点左右,晚上20点左右几乎是所有互联网产品的一个高峰,下单高峰要注意网站的稳定性、可用性。下单高峰时间段也可以考虑进行推广,效果会更佳。
- 按星期分析
df['orderWeek'] = df.createTime.dt.dayofweek + 1
df.groupby('orderWeek').count()['orderId'].plot()
从上面可以看出,上班时间订单量不断上升,在周六达到顶峰,休息时间人们有更强的购买欲望,这也是比较符合现实的。
(5)支付时间分析
可以看一下客户在下单之后多久时间会进行支付:
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()
---------------------------------------
(0, 50] 79229
(100, 1000] 12899
(50, 100] 10674
(1000, 10000] 968
(10000, 100000] 231
Name: payDelta, dtype: int64
从上面可以看出,大部分人下单50秒以内就会进行支付,说明用户基本很少犹豫,购买的目的性很强。
用饼图看一下比例:
pd.cut(df.payDelta, bins).value_counts().plot(kind='pie', autopct='%d%%', shadow=True, figsize=(10, 4))
5、总结
- 通过对电商历史交易数据的清洗和分析,给出一些可以提升销量的建议,当然这只是简单的分析,需要更好的提升销量还需要更加深入和专业的分析才行。
下一篇: 微信公众号开发之通过接口删除菜单