电商交易数据分析

# 加载数据分析需要使用的库
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()
# 加载好数据之后,第一步先分别使用describe和info方法看下数据的大概分布
# 这两个方法放到两个cell中
df.describe()
# 加载device_type
device_type = pd.read_csv('./device_type.txt')
device_type
df.info()
# 首先要做一个数据的清洗
# order_id
# 我们都知道order_id在一个系统里是唯一值
# 先看下有没有重复值
# 注意:当我们对一列取size属性的时候,返回的是行数,如果对于dataframe使用size,返回的是行乘以列的结果,也就是总的元素数
df.orderId.unique().size
df.orderId.size
# 如果有重复值,我们一般最后处理,因为其他的列可能会影响到删除哪一条重复的记录
# 先处理其他的列
# userId
# userId我们只要从上面的describe和info看下值是不是在正常范围就行了
# 对于订单数据,一个用户有可能有多个订单,重复值是合理的
df.userId.unique().size
# productId
# productId最小值是0,先来看下值为0的记录数量
df.productId[(df.productId == 0)].size
# 177条记录,数量不多,可能是因为商品的上架下架引起的,处理完其他值的时候我们把这些删掉
# cityId
# cityId类似于userId,值都在正常范围,不需要处理
df.cityId.unique().size
# price
# price没有空值,且都大于0,注意单位是分,我们把它变成元
df.price = df.price / 100
# payMoney
# payMoney有负值,我们下单不可能是负值,所以这里对于负值的记录要删除掉
# 展示负值的记录
df[df.payMoney < 0]
# 删除负值的记录
df.drop(index=df[df.payMoney < 0].index, inplace=True)
# 在看下,已经没有了
df[df.payMoney < 0].index
# 变成元
df.payMoney = df.payMoney / 100
# channelId
# channelId根据info的结果,有些null的数据,可能是端的bug等原因,在下单的时候没有传channelId字段
# 数据量大的时候,删掉少量的null记录不会影响统计结果,这里我们直接删除
# 展示
df[df.channelId.isnull()]
# 删除
df.drop(index=df[df.channelId.isnull()].index, inplace=True)
# 在查看
df[df.channelId.isnull()]
# deviceType的取值可以看device_type.txt文件,没有问题,不需要处理
# createTime和payTime都没有null,不过我们是要统计2016年的数据,所以把非2016年的删掉
# payTime类似,这里只按创建订单的时间算,就不处理了
# 先把createTime和payTime转换成datetime格式
df.createTime = pd.to_datetime(df.createTime)
df.payTime = pd.to_datetime(df.payTime)
df.dtypes
import datetime
startTime = datetime.datetime(2016, 1, 1)
endTime = datetime.datetime(2016, 12, 31, 23, 59, 59)
# 有16年之前的数据,需要删掉
df[df.createTime < startTime]
df.drop(index=df[df.createTime < startTime].index, inplace=True)
df[df.createTime < startTime]
# payTime早于createTime的也需要删掉
df.drop(index=df[df.createTime > df.payTime].index, inplace=True)
# 处理16年之后的数据
df[df.createTime > endTime]
# 看下支付时间有没有16年以前的,支付时间在16年之后的这里就不处理了
df[df.payTime < startTime]
# 回过头来我们把orderId重复的记录删掉
df.orderId.unique().size
df.orderId.size
df.drop(index=df[df.orderId.duplicated()].index, inplace=True)
df.orderId.unique().size
# 把productId为0的也删除掉
df.drop(index=df[df.productId==0].index, inplace=True)
# 数据清洗完毕,可以开始分析了
# 一般都是先看下数据的总体情况总体情况
# 总订单数,总下单用户,总销售额,有流水的商品数
print(df.orderId.count())
print(df.userId.unique().size)
print(df.payMoney.sum()/100)
print(df.productId.unique().size)
# 分析数据可以从两方面开始考虑,一个是维度,一个是指标,维度可以看做x轴,指标可以看成是y轴,同一个维度可以分析多个指标,同一个维度也可以做降维升维。
# 按照商品的productId
# 先看下商品销量的前十和后十个
productId_orderCount = df.groupby('productId').count()
['orderId'].sort_values(ascending=False)
print(productId_orderCount.head(10))
print(productId_orderCount.tail(10))
# 销售额
productId_turnover = df.groupby('productId').sum()
['payMoney'].sort_values(ascending=False)
print(productId_turnover.head(10))
print(productId_turnover.tail(10))
# 看下销量和销售额最后100个的交集,如果销量和销售额都不行,这些商品需要看看是不是要优化或者下架
problem_productIds =
productId_turnover.tail(100).index.intersection(productId_orderCount.tail(100).index)
# 城市的分析可以和商品维度类似
cityId_orderCount = df.groupby('cityId').count()
['orderId'].sort_values(ascending=False)
cityId_payMoney = df.groupby('cityId').sum()
['payMoney'].sort_values(ascending=False)
# price
# 对于价格,可以看下所有商品价格的分布,这样可以知道什么价格的商品卖的最好
# 先按照100的区间取分桶,价格是分,这里为了好看把他转成元
bins = np.arange(0, 25000, 100)
pd.cut(df.price, bins).value_counts()
# 直方图
# 觉得尺寸小的话可以先设置下figsize,觉得后面的值没有必要展示,可以不用25000,改成10000:
plt.figure(figsize=(16, 16))
plt.hist(df['price'], bins)
# 很多价格区间没有商品,如果有竞争对手的数据,可以看看是否需要补商品填充对应的价格区间
price_cut_count = pd.cut(df.price, bins).value_counts()
zero_cut_result = (price_cut_count == 0)
zero_cut_result[zero_cut_result.values].index
# 按照1000分桶在看下
bins = np.arange(0, 25000, 1000)
price_cut = pd.cut(df.price, bins).value_counts()
# 看看1000分桶的时候5000以下的饼图
m = plt.pie(x=price_cut.values, labels=price_cut.index, autopct='%d%%',
shadow=True)
# channelId
# 渠道的分析类似于productId,可以给出成交量最多的渠道,订单数最多的渠道等,渠道很多时候是需要花钱买流量的,所以还需要根据渠道的盈利情况和渠道成本进行综合比较,同时也可以渠道和商品等多个维度综合分析,看看不同的卖的最好的商品是否相同
# 下单时间分析
# 按小时的下单量分布,可以按时间做推广
# 中午12, 13, 14点下单比较多,应该是午休的时候,然后是晚上20点左右,晚上20点左右几乎是所有互联网产品的一个高峰,下单高峰要注意网站的稳定性、可用性
df['orderHour'] = df.createTime.dt.hour
df.groupby('orderHour').count()['orderId'].plot()
# 按照星期来看,周六下单最多,其次是周四周五
df['orderWeek'] = df.createTime.dt.dayofweek
df.groupby('orderWeek').count()['orderId']
# 下单后多久支付
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()
# 饼图看下,有重合的话可以改下bins
# 绝大部分都在十几分钟之内支付完成,说明用户基本很少犹豫,购买的目的性很强
pd.cut(df.payDelta, bins).value_counts().plot(kind='pie', autopct='%d%%',
shadow=True, figsize=(10, 10))
# 月成交额
# 先把创建订单的时间设置为索引
df.set_index('createTime', inplace=True)
turnover = df.resample('M').sum()['payMoney']
order_count = df.resample('M').count()['orderId']
turnover.plot()