背景:這次的數據分析,主要是針對零售商品行爲。一般企業的後臺都能導出訂單數據,但不一定是所有企業都有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、輸出數據信息:
<class 'pandas.core.frame.DataFrame'>
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 真是高效。以上只是這個開篇的拋磚之作,裏面還有很多內容可以分享,接下來會繼續更新。