一、认识数据处理
为什么要预处理数据?
1、现实世界的数据是“肮脏的”——数据多了,什么问题都会出现
- 不完整的:缺少属性值,缺少感兴趣的属性,或仅包含聚集数据, 如:e.g., Occupation=“”
- 含噪声的:包含错误或者“孤立点”, e.g., Salary=“-10”
- 不一致的:在编码或者命名上存在差异,E.g. Age=“42” Birthday=“03/07/1997” 如:等级代码 前面“1,2,3”, 后面“A, B, C”
2、没有高质量的数据,就没有高质量的挖掘结果
- 高质量的决策必须依赖高质量的数据
为什么数据是肮脏?
1、不完整数据来自:
- 感兴趣的数据难以获得
- 数据收集时与做数据分析时侧重的问题不一致
- 人/硬件/软件问题
2、噪音数据来自数据处理过程:
- 收集–>录入–>传输
3、不一致数据来自:
- 不同数据源
- 数据违背了依赖关系
数据处理的主要任务
1、数据集成
集成多个数据库、数据立方体或文件
2、数据清理
- 填充缺失值
- 识别孤立点,去除噪音
- 修正不一致数据
- 解决由于数据集成造成的数据冗余问题
3、数据规约
得到数据集的压缩表示,它小得多,但可以得到相同或相近的结果,包括维规约和数值规约
4、数据变换
规范化:将数据按比例缩放,使之落入一个小的特定区间
5、数据离散化
离散化:数值属性的原始值用区间标签或概念标签替换,或者标称属性转化为数值属性
二、数据集成
1、横向堆叠-concat
横向堆叠,即将两个表在 X 轴向拼接在一起,可以使用 concat 函数完成,concat 函数 的基本语法如下:
pandas.concat(objs,axis=0,join=‘outer’,join_axes=None,ignore_index=False,keys=None,levels=None, names=None, verify_integrity=False, copy=True)
concat 参数说明表
参数名称 | 说明 |
---|---|
objs | 接收多个 Series,DataFrame,Panel 的组合,表示参与链接的 pandas 对象的列表 的组合,无默认, axis |
join | 接收 inner 或 outer。表示其他轴向上的索引是按交集(inner)还是并集(outer) 进行合并,默认为 outer |
join_axes | 接收 Index 对象,表示用于其他 n-1 条轴的索引,不执行并集/交集运算 |
ignore_index | 接收 boolean,表示是否不保留连接轴上的索引,产生一组新索引 ignore_index range(total_length),默认为 False |
keys | 接收 sequence,表示与连接对象有关的值,用于形成连接轴向上的层次化索引,默 keys 认为 None |
levels | 接收包含多个sequence 的list,表示在指定 keys 参数后,指定用作层次化索引各级别上的索引,默认为 None |
names | 接收 list,表示在设置了 keys 和 levels 参数后,用于创建分层级别的名称,默认为None |
verify_integrity | 接收 boolearn,表示是否检查结果对象新轴上的重复情况,如果发现则引发异常,默认为 False |
当 axis=1 的时候,concat 做行对齐,然后将不同列名称的两张或多张表合并,当两个 表索引不完全一样时,可以使用 join 参数选择是内连接还是外连接,在内连接的情况下, 仅仅返回索引重叠部分,在外连接的情况下,则显示索引的并集部分数据,不足的地方则使用空值填补
当两张表完全一样时,不论 join 参数取值是 inner 或者 outer,结果都是将两个表完 全按照 X 轴拼接起来
2、纵向堆叠-concat
使用 concat 函数时,在默认情况下,即 axis=0 时,concat 做列对齐,将不同行索引 的两张或多张表纵向合并,在两张表的列名并不完全相同的情况下,可 join 参数取值为 inner 时,返回的仅仅是列名交集所代表的列,取值为 outer 时,返回的是两者列名的并集 所代表的列,其原理示意如图
不论 join 参数取值是 inner 或者 outer,结果都是将两个表完全按照 Y 轴拼接起来
代码实现:
import pandas as pd
# 加载数据
df1 = pd.read_excel('./concat直接拼接数据.xlsx', sheet_name=0, index_col=0)
print('df1:\n', df1)
df2 = pd.read_excel('./concat直接拼接数据.xlsx', sheet_name=1, index_col=0)
print('df2:\n', df2)
# 可以是pd.concat来进行横向堆叠
# 当axis=1,join= 'outer'
# 在列的方向直接拼接,在行的方向,拿取所有的行,在没有数据的行的位置用NaN来补齐
res = pd.concat((df1, df2), axis=1, join='outer')
print('res:\n',res)
# 当axis =1 ,join = 'inner'
# 在列的方向上直接拼接,在行的方向,取共同拥有的行
res = pd.concat((df1, df2), axis=1, join='inner')
print('res:\n', res)
# pd.concat来进行纵向堆叠
# 当axis=0, join = 'outer'
# 在行的方向,直接拼接,在列的方向,拿取所有的列,在没有值的列的位置用NaN来补齐
res = pd.concat((df1, df2), axis=0, join='outer', sort=False)
print('res:\n', res)
# 当axis=0,join='inner'
# 在行的方向,直接拼接,在列的方向,拿取共同拥有的列
res = pd.concat((df1, df2), axis=0, join='inner', sort=False)
print('res:\n', res)
3、纵向堆叠-append
append 方法也可以用于纵向合并两张表。但是 append 方法实现纵向表堆叠有一个前提 条件,那就是两张表的列名需要完全一致。append 方法的基本语法如下
pandas.DataFrame.append(self, other, ignore_index=False, verify_integrity=False)
append 参数说明表
参数名称 | 说明 |
---|---|
other | 接收 DataFrame 或 Series。表示要添加的新数据,无默认 |
ignore_index | 接收 boolean,如果输入 True,会对新生成的 DataFrame 使用新的索引(自动产 生)而忽略原来数据的索引,默认为 False |
verify_integrity | 接收 boolean,如果输入 True,那么当 ignore_index 为 False 时,会检查添加的 数据索引是否冲突,如果冲突,则会添加失败,默认为 False |
代码实现:
# 也可以使用append来进行纵向堆叠
df1 = pd.read_excel('./append直接拼接数据.xlsx', sheet_name=0, index_col=0)
print('df1:\n', df1)
df2 = pd.read_excel('./append直接拼接数据.xlsx', sheet_name=1, index_col=0)
print('df2:\n', df2)
# 和 pd.concat 的axis=0,join='outer' 相同,一般情况下,要求在列名相同时使用
res = df1.append(df2, sort=False)
print('res:\n', res)
三、案例:垂钓装备合并案例
近年来,随着人们的生活水平的提高,人们对于精神生活品质的要求越来越高,于是, 各种娱乐活动出现,其中,钓鱼属于一种户外运动,目标是用渔具把鱼从水里钓上来,而且 钓鱼不限制性别与年龄,大人小孩子都喜欢,钓鱼亲近大自然,陶冶情操,然而在钓鱼的时 候,钓鱼装备又影响着钓鱼的成果,所以,越来越多的钓友对于钓鱼装备的要求越来越高, 对于钓鱼装备的需求也越来越多,那么对于钓鱼装备的销售公司来说,了解客户对于不同品牌的钓鱼装备的喜爱程度,对于销售公司来说至关重要
以下为某钓鱼装备公司的销售记录,针对于销售记录,来确定客户最喜爱的品牌或者最火品牌
以下为每类钓鱼装备销售记录细表(表结构类似):
钓鱼装备&抄网销售记录细表(部分)
日期 | 转化率 | 访客数 | 三级类目 | 客单价 | 品牌 |
---|---|---|---|---|---|
2019-08 | 0.075437 | 448725 | 抄网 | 28.347 | 品牌-7 |
2019-08 | 0.066758 | 303676 | 抄网 | 35.92695 | 品牌-1 |
2019-08 | 0.029469 | 253084 | 抄网 | 65.60413 | 品牌-5 |
2019-08 | 0.032616 | 166098 | 抄网 | 82.162 | 品牌-10 |
2019-08 | 0.080396 | 173662 | 抄网 | 31.35206 | 品牌-13 |
钓鱼装备&钓竿销售记录细表(部分)
日期 | 转化率 | 访客数 | 三级类目 | 客单价 | 品牌 |
---|---|---|---|---|---|
2019-08 | 0.029797 | 3939046 | 钓竿 | 135.6066 | 品牌-3 |
2019-08 | 0.027249 | 1948598 | 钓竿 | 254.9653 | 品牌-19 |
2019-08 | 0.031458 | 829839 | 钓竿 | 478.2628 | 品牌-16 |
2019-08 | 0.017834 | 938215 | 钓竿 | 670.2237 | 品牌-2 |
2019-08 | 0.00864 | 522226 | 钓竿 | 1729.252 | 品牌-18 |
到底如何理解最火品牌?其实可以转化为确定哪个品牌的销售额最高,那么该品牌就是最火的品牌,会发现在各个类别的销售记录细表中,并不存在着销售额特征字段,但是可以通过“销售额=访问数 * 转化率乘于 客单价”来确定销售额
代码实现:
import pandas as pd
import os
import time
# 开始
start = time.time()
# # 以绑钩器 为例,来先研究 不同的品牌 跟销售额之间的关系
#
excel_name = '垂钓装备&绑钩器.xlsx'
# # 加载数据
data = pd.read_excel('./data/' + excel_name)
# print('data:\n', data)
# print('data:\n', data.columns)
# 计算销售额
# 销售额 = 访客数 * 转化率 * 客单价
data.loc[:, '销售额'] = data.loc[:, '访客数'] * data.loc[:, '转化率'] * data.loc[:, '客单价']
print('data:\n', data)
print('data:\n', data.columns)
# 按照品牌进行分组,统计 销售额的 sum
res = pd.pivot_table(data=data,
index='品牌',
values='销售额',
aggfunc='sum').reset_index().sort_values(by='销售额', ascending=False)
# 可以添加行业
res['行业'] = excel_name.split('.')[0]
print('res:\n', res)
# 以整个 垂钓装备 为例
# 获取所有文件名称
file_list = os.listdir('./data/')
print('file_list:\n', file_list)
# 创建一个空的df
res = pd.DataFrame()
# 遍历
for excel_name in file_list:
# print('excel_name:\n', excel_name) # 代表是不同的装备excel
# 对 每一个excel 进行操作
data = pd.read_excel('./data/' + excel_name, sheet_name=0)
# print('data:\n', data)
# print('data:\n', data.columns)
# 计算其 营业额
data.loc[:, '营业额'] = data.loc[:, '访客数'] * data.loc[:, '转化率'] * data.loc[:, '客单价']
# 按照品牌进行分组,统计 营业额的 sum
df