電商客戶特征識別數據分析報告:數據規整和思路
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
# plt.style.use('seaborn') # 改變圖像風格
plt.rcParams['font.family'] = ['Arial Unicode MS', 'Microsoft Yahei', 'SimHei', 'sans-serif'] # 解決中文亂碼
# plt.rcParams['axes.unicode_minus'] = False # simhei黑體字 負號亂碼 解決
數據載入
shop = pd.read_excel('shopmall.xlsx', None)
shop
OrderedDict([('訂單信息', 訂單ID 客戶ID 訂單狀態 優惠類型
0 47739 5245 1 0
1 341269 5245 0 0
2 32690 5254 1 0
3 45641 5254 1 0
4 66116 5254 1 0
5 79014 5254 1 0
6 79058 5254 0 0
7 79221 5254 1 0
8 79608 5254 1 0
9 146455 5254 1 0
10 148275 5254 1 0
11 149066 5254 1 1
12 240219 5286 1 1
13 287500 5286 1 0
14 287502 5286 0 0
15 290370 5286 0 0
16 290372 5286 0 0
17 378615 5286 0 0
18 378618 5286 0 0
19 378621 5286 0 0
20 66457 5292 1 0
21 211972 5292 0 1
22 226715 5292 1 0
23 237862 5292 0 1
24 246600 5292 1 0
25 248991 5292 0 1
26 249847 5292 1 1
27 256960 5292 1 1
28 422975 5292 1 0
29 148707 5474 1 0
... ... ... ... ...
29120 445946 169197 0 1
29121 442081 169217 1 1
29122 442299 169269 1 1
29123 442333 169276 1 1
29124 442649 169299 0 1
29125 442726 169299 1 1
29126 443197 169318 1 1
29127 444034 169318 1 1
29128 443767 169393 0 1
29129 443770 169393 1 0
29130 443771 169393 1 0
29131 444237 169393 1 0
29132 443940 169445 0 1
29133 444077 169445 1 0
29134 445037 169445 0 0
29135 444721 169598 1 0
29136 445432 169598 0 1
29137 445444 169598 1 1
29138 444984 169613 1 1
29139 445427 169614 1 1
29140 445249 169691 1 1
29141 445279 169699 1 0
29142 447620 169699 1 1
29143 445884 169815 1 1
29144 447102 169832 1 1
29145 446758 169934 1 1
29146 446759 169934 1 0
29147 447165 169976 0 1
29148 447274 169976 0 1
29149 447375 169976 1 1
[29150 rows x 4 columns]),
('貨物信息', 訂單ID 貨物ID 貨物名稱 優惠額度
0 264971 103247 自然樂園水果禮盒 >15
1 264994 103247 自然樂園水果禮盒 >15
2 266829 103247 自然樂園水果禮盒 >15
3 267232 103247 自然樂園水果禮盒 >15
4 269051 103247 自然樂園水果禮盒 >15
5 256809 101645 紫甘藍 >15
6 256984 101645 紫甘藍 >15
7 258700 101645 紫甘藍 >15
8 268496 101645 紫甘藍 >15
9 268510 101645 紫甘藍 >15
10 275809 101645 紫甘藍 >15
11 277573 101645 紫甘藍 >15
12 284473 101645 紫甘藍 >15
13 287662 101645 紫甘藍 >15
14 287668 101645 紫甘藍 >15
15 289079 101645 紫甘藍 >15
16 290400 101645 紫甘藍 >15
17 264515 103306 滋久 >15
18 266465 103306 滋久 >15
19 266994 103306 滋久 >15
20 272357 103306 滋久 >15
21 277529 103306 滋久 >15
22 258249 103305 滋久 >15
23 260035 103305 滋久 >15
24 263743 103305 滋久 >15
25 268881 103305 滋久 >15
26 271752 104052 豬蹄(一只) >15
27 274915 104052 豬蹄(一只) >15
28 276892 104052 豬蹄(一只) >15
29 277573 104052 豬蹄(一只) >15
... ... ... ... ...
3100 284553 102103 冷凍鮮肉 0
3101 284927 102103 冷凍鮮肉 0
3102 285226 102103 冷凍鮮肉 0
3103 285307 102103 冷凍鮮肉 0
3104 285552 102103 冷凍鮮肉 0
3105 286058 102103 冷凍鮮肉 0
3106 286168 102103 冷凍鮮肉 0
3107 286815 102103 冷凍鮮肉 0
3108 287216 102103 冷凍鮮肉 0
3109 287519 102103 冷凍鮮肉 0
3110 291209 102103 冷凍鮮肉 0
3111 291234 102103 冷凍鮮肉 0
3112 291584 102103 冷凍鮮肉 0
3113 292142 102103 冷凍鮮肉 0
3114 284006 104323 牙簽 0
3115 263864 103376 500元充值卡 0
3116 268178 103376 500元充值卡 0
3117 268277 103376 500元充值卡 0
3118 285796 103376 500元充值卡 0
3119 286098 103376 500元充值卡 0
3120 257077 103376 500元充值卡 0
3121 261240 103376 500元充值卡 0
3122 265594 103376 500元充值卡 0
3123 265982 103376 500元充值卡 0
3124 266432 103376 500元充值卡 0
3125 282903 103376 500元充值卡 0
3126 283994 103376 500元充值卡 0
3127 284171 103376 500元充值卡 0
3128 256095 103376 500元充值卡 0
3129 256499 103376 500元充值卡 0
[3130 rows x 4 columns]),
('顧客信息',
客戶ID 登陸次數 注冊時間(距1970-1-1的秒數) 本次購買時間(距1970-1-1的秒數) 經驗值 訂單數
0 5245 55 1430413266 1495339734 206 1
1 5254 69 1430413266 1499041945 428 13
2 5286 57 1430413266 1509936376 280 1
3 5292 184 1430413266 1510135868 643 5
4 5474 71 1430413266 1481185064 61 2
5 5544 520 1430413266 1511065463 5033 103
6 5547 30 1430413266 1510577047 477 8
7 5552 2699 1430413266 1511245956 12673 164
8 5560 39 1430413266 1481811865 27 0
9 5580 137 1430413266 1506301413 236 2
10 5625 463 1430413266 1510935255 2087 14
11 5628 356 1430413266 1511145498 11494 166
12 5661 11675 1430413266 1511224143 34701 487
13 5690 1769 1430413266 1511175196 13398 182
14 5699 634 1430413266 1510274405 8415 121
15 5701 94 1430413266 1481201883 512 8
16 5723 29 1430413266 1488960790 163 2
17 5725 1372 1430413266 1510625605 9243 126
18 5726 1576 1430413266 1511162452 13078 193
19 5727 102 1430413266 1510223946 2574 37
20 5728 164 1430413266 1498397004 863 16
21 5734 1193 1430413266 1511169496 6852 86
22 5740 826 1430413266 1506164574 2309 19
23 5767 80 1430413266 1506216500 1681 17
24 5785 62 1430413266 1506783217 249 5
25 5789 170 1430413266 1511140849 1373 20
26 5804 730 1430413266 1511190699 2851 28
27 5816 374 1430413266 1508748129 1225 15
28 5880 206 1430413266 1511146306 3913 70
29 5912 288 1430413266 1510033445 1755 26
... ... ... ... ... ... ...
2970 168758 18 1510124356 1510960789 105 2
2971 168792 15 1510136872 1510661772 60 1
2972 168831 78 1510182960 1511241351 635 10
2973 168834 12 1510187047 1511239077 102 3
2974 168948 6 1510233924 1510234362 48 1
2975 168976 7 1510275950 1511166273 66 3
2976 168981 30 1510278673 1511184888 146 2
2977 168991 6 1510280818 1510456811 129 3
2978 169031 10 1510287019 1510613142 27 1
2979 169049 7 1510292348 1510392612 43 1
2980 169084 11 1510303482 1510927533 94 1
2981 169106 23 1510312431 1511054357 215 2
2982 169132 18 1510324837 1511090706 75 2
2983 169197 38 1510373093 1510890780 66 1
2984 169217 28 1510377281 1510877581 38 1
2985 169269 4 1510388952 1510388952 7 1
2986 169276 6 1510391145 1511008391 50 1
2987 169299 9 1510397978 1511187978 27 1
2988 169318 8 1510407061 1510615622 154 2
2989 169393 14 1510464820 1511147607 187 3
2990 169445 13 1510487420 1510645072 84 1
2991 169598 35 1510618726 1510983354 63 2
2992 169613 11 1510627070 1510746988 12 1
2993 169614 9 1510627121 1510889773 33 1
2994 169691 6 1510657422 1510706666 73 1
2995 169699 20 1510662595 1511217077 153 3
2996 169815 13 1510753437 1511159975 57 1
2997 169832 12 1510793074 1511142183 62 1
2998 169934 14 1510841381 1510971292 68 2
2999 169976 16 1510908302 1511184987 27 1
[3000 rows x 6 columns])])
dingdan = shop['訂單信息']
dingdan.head()
image.png
huowu = shop['貨物信息']
huowu.head()
image.png
guke = shop['顧客信息']
guke.head()
image.png
數據規整
檢查數據是否有缺失值和異常列類型
dingdan.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 29150 entries, 0 to 29149
Data columns (total 4 columns):
訂單ID 29150 non-null int64
客戶ID 29150 non-null int64
訂單狀態 29150 non-null int64
優惠類型 29150 non-null int64
dtypes: int64(4)
memory usage: 911.0 KB
huowu.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 3130 entries, 0 to 3129
Data columns (total 4 columns):
訂單ID 3130 non-null int64
貨物ID 3130 non-null int64
貨物名稱 3130 non-null object
優惠額度 3130 non-null object
dtypes: int64(2), object(2)
memory usage: 97.9+ KB
guke.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 3000 entries, 0 to 2999
Data columns (total 6 columns):
客戶ID 3000 non-null int64
登陸次數 3000 non-null int64
注冊時間(距1970-1-1的秒數) 3000 non-null int64
本次購買時間(距1970-1-1的秒數) 3000 non-null int64
經驗值 3000 non-null int64
訂單數 3000 non-null object
dtypes: int64(5), object(1)
memory usage: 140.7+ KB
顧客信息表,訂單數 列,數據類型錯誤
guke.head()
image.png
正常數據類型為整型
guke.loc[1, '訂單數']
type(guke.loc[1, '訂單數'])
# 判斷數據類型是否是整型
type(guke.loc[1, '訂單數']) == int
type(guke.loc[1, '訂單數']) == np.int
True
guke['訂單數']
0 1
1 13
2 1
3 5
4 2
5 103
6 8
7 164
8 0
9 2
10 14
11 166
12 487
13 182
14 121
15 8
16 2
17 126
18 193
19 37
20 16
21 86
22 19
23 17
24 5
25 20
26 28
27 15
28 70
29 26
...
2970 2
2971 1
2972 10
2973 3
2974 1
2975 3
2976 2
2977 3
2978 1
2979 1
2980 1
2981 2
2982 2
2983 1
2984 1
2985 1
2986 1
2987 1
2988 2
2989 3
2990 1
2991 2
2992 1
2993 1
2994 1
2995 3
2996 1
2997 1
2998 2
2999 1
Name: 訂單數, Length: 3000, dtype: object
自定義函數獲取類型異常值所在行
def aaa(x):
# return x
# if type(x) == int:
# return False
# else:
# return True
# 三元表達式
return False if type(x) == int else True
guke['訂單數'].apply(aaa)
guke[guke['訂單數'].apply(aaa)]
image.png
修正錯誤數據
用經驗值列判斷錯誤訂單數數據不適合
guke2 = guke.copy() # 副本
# 用經驗值列判斷錯誤訂單數數據不適合,數據太多
# guke[(guke['經驗值'] >= 1100) & (guke['經驗值'] <= 1200)]
guke[guke['登陸次數'] >= 2800]
image.png
計算獲取數據訂單數平均值或中位數,填入錯誤單元格
方法1:求所選范圍平均值或中位數
特點:套路,無腦操作
# guke[(guke['登陸次數'] >= 2800)]['訂單數'].median() # 直接計算平均值錯誤,字符串列不能計算
guke2.loc[46, '訂單數'] = np.nan # 字符串錯誤值替換為缺失值
guke2[guke2['登陸次數'] >= 2800]
guke2[guke2['登陸次數'] >= 2800]['訂單數'].median() # 求中位數運算
209.0
# 用中位數替換缺失值
guke2.loc[46, '訂單數'] = 209
guke2[guke2['登陸次數'] >= 2800]
image.png
guke2.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 3000 entries, 0 to 2999
Data columns (total 6 columns):
客戶ID 3000 non-null int64
登陸次數 3000 non-null int64
注冊時間(距1970-1-1的秒數) 3000 non-null int64
本次購買時間(距1970-1-1的秒數) 3000 non-null int64
經驗值 3000 non-null int64
訂單數 3000 non-null int64
dtypes: int64(6)
memory usage: 140.7 KB
方法2:求所選范圍中位數,另一種方式(跳過錯誤值,直接進行運算)
特點:需要觀察數據后操作
guke[guke['登陸次數'] > 2829]['訂單數'].median() # 求中位數運算
209.0
方法3:從另一個訂單表內提取客戶ID相同行數,得出本ID訂單數
不完全對應,但準確率超過自行求值
- 優點:最精確
- 缺點:碰巧。方法不具普適性,僅在少數情況下能夠使用
- 需要超凡的洞察力,大力研究表格
# 顧客表客戶id對應的訂單數
guke.loc[12, '訂單數']
dingdan[(dingdan['客戶ID'] == 5661)].shape[0]
487
dingdan[(dingdan['客戶ID'] == 6243)].shape[0]
146
# 修改錯誤值
guke.loc[46, '訂單數'] = 146
guke[guke['登陸次數'] >= 2800]
image.png
guke.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 3000 entries, 0 to 2999
Data columns (total 6 columns):
客戶ID 3000 non-null int64
登陸次數 3000 non-null int64
注冊時間(距1970-1-1的秒數) 3000 non-null int64
本次購買時間(距1970-1-1的秒數) 3000 non-null int64
經驗值 3000 non-null int64
訂單數 3000 non-null int64
dtypes: int64(6)
memory usage: 140.7 KB
正常
快速統計,查看異常值
dingdan.describe()
image.png
huowu.describe()
image.png
guke.describe()
image.png
保存規整后數據
writer = pd.ExcelWriter('shopmall2.xlsx')
dingdan.to_excel(
writer, # 寫入數據
'訂單信息', # 工作表標簽
index=False # 不存入行索引
)
huowu.to_excel(
writer, # 寫入數據
'貨物信息', # 工作表標簽
index=False # 不存入行索引
)
guke.to_excel(
writer, # 寫入數據
'顧客信息', # 工作表標簽
index=False # 不存入行索引
)
writer.save()
延展思路
數據分析基本流程:
- 提出問題
- 準備數據
- 分析數據
- 指標創建
- 數據可視化
- 洞察結論
貨物信息表
- 不同優惠額度的訂單數量
- 能否根據優惠額度分組可視化產品銷量情況
- 能否輸出正常價格下銷量最好的前10個產品
- 能否輸出優惠價格下銷量最好的前10個產品
訂單信息表
- 能否根據訂單狀態篩選出已完成訂單
- 能否根據客戶id和優惠類型分出 正常客戶和無價值客戶
顧客信息表
- 能否將訂單信息表得出的 正常客戶和無價值客戶列,合并到本表中
- 能否通過客戶id列,和正常、無效客戶列,得出正常和無效客戶分別在:
- 登陸次數,注冊時間,本次購買時間,經驗值,訂單數,等指標下的對比差異?
- 注冊和登錄時間間隔的對比差異?