电商客户特征识别数据分析报告:数据规整和思路
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列,和正常、无效客户列,得出正常和无效客户分别在:
- 登陆次数,注册时间,本次购买时间,经验值,订单数,等指标下的对比差异?
- 注册和登录时间间隔的对比差异?