背景:这次的数据分析,主要是针对零售商品行为。一般企业的后台都能导出订单数据,但不一定是所有企业都有BI系统。所以这里先简单介绍下订单的简易处理之路。而这,只是一个开篇。
数据:共41345条数据,文件格式为csv。数据已经通过数据库导出并保存为csv文件,通常都建议导出为csv文件,因为csv属于通用型文件。
工具:使用python+pandas
使用的的编辑环境:pycharm
下面开始代码演示:
导入相应包上,这个是”行业“规矩,后来者就尽量别破坏了。
import pandas as pd # 导入pandas
import numpy as np # 导入numpy
import matplotlib.pyplot as plt # 导入matplotlib的绘图库
由于使用的是pycharm,所以开始工作前要设置一下控制台的显示方式,这样结果显示出来会更友好。
# 开始工作前建议先设置以下两个参数,这样方便调式和查看结果
pd.set_option('display.width', 160) # 设置控制台显示的宽度,参数160是因为我的显示器显示160是最合适
pd.set_option('display.max_columns', 500) # 设置可以显示多少列
个人觉得,文件将其保存为一个变量,方便将来重复利用会比较好,提示:文件中尽量不要出现中文名字,不然到下一步用pandas读取文件的时候会有莫名奇妙的报错。
# 第一步:读取文件信息
file_path = r'C:\Users\Jacky\Desktop\csdn\sample.csv' # 文件路径,以后只需要修改这里,就可以重复利用
特别注意parse_dates的参数,这个是用来确定哪一列是代表datetime类型的。但是不一定要这里设置,后面再设置也是可以的。
# 读取文件并赋值给data,header代表第0行为列名,这是默认值,parse_dates指定哪一列为日期,可以一开始的时候就设定,也可以后
# 期使用的时候指定
data = pd.read_csv(file_path, header=0, parse_dates=['create_date', 'update_date', 'pay_time'])
以首先来看一下,读取的数据包含哪些列,和这些列的简单数据描述,这里是用.describe()方法。
# 第二步:简单数据清洗
# 以python的方法查看表格内容
print('1、包含哪些列:\n', data.columns)
print("-" * 100) # 分隔线
print('2、简单统计:\n', data.describe())
结果如下:
1、包含哪些列:
Index(['id', 'create_by', 'create_date', 'update_by', 'update_date', 'remarks', 'del_flag', 'shop_id', 'pay_time', 'status', 'order_amount', 'pay_amount',
'customer', 'cost_amount', 'profit_amount'],
dtype='object')
----------------------------------------------------------------------------------------------------
2、简单统计:
create_by update_by remarks del_flag status order_amount pay_amount cost_amount profit_amount
count 0.0 0.0 0.0 41345.0 41345.000000 41345.000000 41345.000000 37931.000000 37931.000000
mean NaN NaN NaN 0.0 0.917427 5.469057 5.181514 3.256458 1.822723
std NaN NaN NaN 0.0 0.275240 5.529029 4.760806 3.326059 2.481224
min NaN NaN NaN 0.0 0.000000 0.500000 0.340000 0.000000 -34.260000
25% NaN NaN NaN 0.0 1.000000 3.000000 3.000000 1.680000 0.650000
50% NaN NaN NaN 0.0 1.000000 4.500000 4.000000 2.630000 1.180000
75% NaN NaN NaN 0.0 1.000000 6.000000 6.000000 4.080000 2.210000
max NaN NaN NaN 0.0 1.000000 187.600000 156.000000 121.450000 123.480000
----------------------------------------------------------------------------------------------------
通常拿到一个文件,先看一看有哪些列,和这些数据的一些描述(describe()),还有就是要和我们的运营业务相联系,看哪些列是要保留的。
# 可以看到,'create_by', 'update_by', 'remarks'都是空列,这个我们后续就无需使用了。
# 将空列删除,保留有数据的列
data = data.dropna(axis=1, how='all') # axis=1代表以列去查找空值,how='all'代表整理为空则删除
print('-' * 100)
print('3、现在保留的列:\n', data.columns)
清清后的列,现在保留哪下:
3、现在保留的列:
Index(['id', 'create_date', 'update_date', 'del_flag', 'shop_id', 'pay_time', 'status', 'order_amount', 'pay_amount', 'customer', 'cost_amount',
'profit_amount'],
dtype='object')
# 列说明: # id:订单号 # create_date:订单创建日期 # update_date:订单更改日期 # del_flag:删除标记,此列其实无用,可以清理 # shop_id:店铺编号,一个店有一个唯一编号 # pay_time: 支付时间 # status: 状态, 0 为未支付,1为已支付 # order_amount: 订单金额 # pay_amount: 支付金额 # customer: 客户 # cost_amount: 成本 # profit_amount: 利润 # 把del_flag 列清除
以上这些数据列,不同的业务场景可能有不同意的意义,作为运营或分析人员,必需要联系具体的业务,并且要对业务有所了解。然后再进行数据清洗:
data = data.drop('del_flag', axis=1)
print('-' * 100)
print('4、输出数据信息:\n')
print(data.info()) # info()方法可以看到数据各列的信息,可以看出有些列是有空值,原因是因为有些订单是没有成交的
这次使用.info()的方法来查看数据信息。这里想说明的时.describe和.info()这两个方法要经常一起使用。
4、输出数据信息:
RangeIndex: 41345 entries, 0 to 41344
Data columns (total 11 columns):
id 41345 non-null object
create_date 41345 non-null datetime64[ns]
update_date 3414 non-null datetime64[ns]
shop_id 41345 non-null object
pay_time 37931 non-null datetime64[ns]
status 41345 non-null int64
order_amount 41345 non-null float64
pay_amount 41345 non-null float64
customer 41345 non-null object
cost_amount 37931 non-null float64
profit_amount 37931 non-null float64
dtypes: datetime64[ns](3), float64(4), int64(1), object(3)
memory usage: 3.0+ MB
下一步,就进入业务数据的探索:
# 第三步:之前的数据准备都差不多了,现在可以看看有多少订单是成交的。
print('-'*100)
print('5、订单成交量:\n', data['status'].value_counts())
# 成交有37931单,未成交的有3414单
这里有个方法是.value_counts(),这个方法是可以将data[‘status’]列的所有值作一次计数,因为这列包含的是订单是否成交的信息,所以1代表成交,二代表未成交。
5、订单成交量:
1 37931
0 3414
Name: status, dtype: int64
以下都是进行静态的数据指标统计:
# 计算该订单支付率:成交订单/所有订单*100%
print('-'*100)
print("6、订单支付率:{:.2%}".format(data['status'].value_counts()[1]/data['status'].size))
# 计算静态指标
print('-'*100)
print('7、订单金额:¥{:.2f}'.format(data[data['status'] == 1]['order_amount'].sum()))
print('8、实收金额:¥{:.2f}'.format(data[data['status'] == 1]['pay_amount'].sum()))
print('9、成本金额:¥{:.2f}'.format(data[data['status'] == 1]['cost_amount'].sum()))
print('10、盈利金额:¥{:.2f}'.format(data[data['status'] == 1]['profit_amount'].sum()))
print('11、订单量:{}'.format(data[data['status'] == 1]['id'].count()))
print('12、成交用户数:{}'.format(data[data['status'] == 1]['customer'].nunique()))
print('13、客单价:{:.2f}'.format(data[data['status'] == 1]['order_amount'].sum() /
data[data['status'] == 1]['customer'].drop_duplicates().count()))
print('14、每单均价:{:.2f}'.format(data[data['status'] == 1]['pay_amount'].sum() /
data[data['status'] == 1]['id'].count()))
print('15、折扣率:{:.2f}%'.format(data[data['status'] == 1]['pay_amount'].sum() /
data[data['status'] == 1]['order_amount'].sum()*100))
print('16、每单盈利:¥{:.2f}'.format(data[data['status'] == 1]['profit_amount'].sum() /
data[data['status'] == 1]['id'].count()))
print('17、毛利率:{:.2f}%'.format(data[data['status'] == 1]['profit_amount'].sum() /
data[data['status'] == 1]['pay_amount'].sum()*100))
print('18、促销费用(订单金额 - 实收金额):¥{:.2f}'.format(data[data['status'] == 1]['order_amount'].sum() -
data[data['status'] == 1]['pay_amount'].sum()))
以下是结果:
6、订单支付率:91.74%
----------------------------------------------------------------------------------------------------
7、订单金额:¥200845.34
8、实收金额:¥192658.42
9、成本金额:¥123520.70
10、盈利金额:¥69137.72
11、订单量:37931
12、成交用户数:12140
13、客单价:16.54
14、每单均价:5.08
15、折扣率:95.92%
16、每单盈利:¥1.82
17、毛利率:35.89%
18、促销费用(订单金额 - 实收金额):¥8186.92
静态指标只是一个方法,数据分析最重要的一点是做比较!比较!比较 !重要事情说三遍!
由于这份数据包含日该业务在一段时间内,各店铺的经营状况总结,这里先简单做一个日期的比较。
# 变化趋势,为了不影响原数据,所以复制一份新的。
data2 = data.copy()
print('-'*100)
# 由于'create_date', 'update_date' , 'pay_time'带有完整的年月日时分秒,而我们这一步分析只需要到日,所以要做转换
# 通过.dt可以获得日期的很多属性,具体可以参考文档
data2['c_date'] = pd.to_datetime(data2['create_date'].dt.date)
# 一天有多个订单,现在需要按天将各指标统计出来,所以需要用到groupby
data2_gb_date = data2[data2['status'] == 1].groupby('c_date')
result = data2_gb_date.agg({'id': np.size,
'order_amount': sum,
'pay_amount': sum,
'cost_amount': sum,
'profit_amount': sum,
'customer': pd.Series.nunique,
'shop_id': pd.Series.nunique})
print(result.rename(columns={'id': '订单量',
'order_amount': '订单金额',
'pay_amount': '实付金额',
'cost_amount': '成本金额',
'profit_amount': '盈利金额',
'customer': '成交用户(去重)',
'shop_id': '成交点位数(去重)'}))
以下是按天统计得出的结果,可以对比这段时间内的经营状况。
订单量 订单金额 实付金额 成本金额 盈利金额 成交用户(去重) 成交点位数(去重)
c_date
2018-04-01 656 4084.50 3998.53 2551.10 1447.43 536 213
2018-04-02 1543 8771.95 8572.29 5313.28 3259.01 1306 390
2018-04-03 1580 9041.00 8708.92 5358.40 3350.52 1358 400
2018-04-04 1497 8440.40 8081.70 4902.19 3179.51 1274 390
2018-04-05 500 2898.50 2766.05 1620.40 1145.65 395 141
2018-04-06 552 3275.60 3129.74 1766.36 1363.38 455 174
2018-04-07 789 4705.20 4579.29 2710.67 1868.62 665 220
2018-04-08 1308 7331.90 7062.43 4070.43 2992.00 1136 375
2018-04-09 1476 8404.63 7863.06 4613.59 3249.47 1257 409
2018-04-10 1479 8131.98 7896.51 4512.99 3383.52 1277 419
2018-04-11 1397 7907.05 7614.83 4368.06 3246.77 1229 401
2018-04-12 1596 8797.77 8319.40 5173.24 3146.16 1380 445
2018-04-13 1655 9186.70 8591.64 5703.61 2888.03 1382 424
2018-04-14 1149 5916.20 5707.89 3677.34 2030.55 963 331
2018-04-15 698 3459.80 3358.32 2113.40 1244.92 567 219
2018-04-16 1606 8252.40 7980.36 5059.78 2920.58 1385 424
2018-04-17 1465 7562.90 7303.96 4673.80 2630.16 1263 426
2018-04-18 1452 6906.90 6653.96 4463.29 2190.67 1224 403
2018-04-19 1591 7838.20 7433.22 5140.59 2292.63 1345 416
2018-04-20 1599 7955.10 7719.04 5108.78 2610.26 1387 409
2018-04-21 969 4691.10 4562.20 3040.62 1521.58 812 311
2018-04-22 559 2938.20 2824.69 1806.94 1017.75 476 209
2018-04-23 1414 7056.90 6716.17 4632.27 2083.90 1202 384
2018-04-24 1564 8069.90 7644.05 5306.90 2337.15 1333 404
2018-04-25 1593 7667.86 7300.24 4922.71 2377.53 1348 400
2018-04-26 1868 9623.74 9102.45 6455.44 2647.01 1555 430
2018-04-27 1659 7889.10 7596.77 5168.48 2428.29 1387 403
2018-04-28 1625 8400.68 8029.21 5589.55 2439.66 1381 400
2018-04-29 561 2951.50 2901.43 1973.12 928.31 469 201
2018-04-30 531 2687.68 2640.07 1723.37 916.70 415 168
以下是关于这段时间内的业务统计结论,注意使用格式化输出.format的使用,可以很方法的按使用者的意图输出内容。
print('最高成金额日期为:{:%Y/%m/%d}'.format(result['pay_amount'].idxmax()))
print('最高成交金额为:{:.2f}'.format(result.loc[result['pay_amount'].idxmax(), 'pay_amount']))
print('最多企业成交的日期为:{:%Y/%m/%d}'.format(result['shop_id'].idxmax()))
print('最大企业成交数为:{}'.format(result.loc[result['shop_id'].idxmax(), 'shop_id']))
结果如下:
最高成金额日期为:2018/04/26
最高成交金额为:9102.45
最多企业成交的日期为:2018/04/12
最大企业成交数为:445
以上是简单展示了一些pandas 处理数据的思路,有些人可能觉得其实用EXCEL可能会更简单,但是当要应付大数据时代,excel可能会力不从心。我对自己的Excel也是相当有信心,但是觉得python+pandas 真是高效。以上只是这个开篇的抛砖之作,里面还有很多内容可以分享,接下来会继续更新。