Travel Tips
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
第 3 章 11 条数据化运营不得不知道的数据预处理经验一
数据预处理是数据化运营过程中的重要环节,它直接决定了后期所有数据工作的质量和价值输出。从数据预处理的主要内容看,包括数据清洗、转换、归约、聚合、抽样等。
在数据清洗过程中,主要处理的是缺失值、异常值和重复值。所谓清洗,是对数据集进行丢弃、填充、替换、去重等操作,实现去除异常、纠正错误、补足缺失的目的。数据列缺失的 4 种处理方法
数据缺失分为两种:一是行记录的缺失,这种情况又称数据记录丢失;二是数据列值的缺失,即由于各种原因导致的数据记录中某些列的值空缺,不同的数据存储和环境中对于缺失值的表示结果也不同,例如,数据库中是 Null , Python 返回对象是 None , Pandas 或 Numpy 中是NaN 。
注意:在极少数情况下,部分缺失值也会使用空字符串来代替,但空字符串绝对不同于缺失值。从对象的实体来看,空字符串是有实体的,实体为字符串类型;而缺失值其实没有实体的,即没有数据类型。丢失的数据记录通常无法找回,这里重点讨论数据列类型缺失值的处理,通常有四种思路:
以下任意一种场景都不宜采用该方法:
· 数据集总体中存在大量的数据记录不完整情况且比例较大,例如超过 10% ,删除这些带有缺失值的记录意味着将会损失过多有用信息。
· 带有缺失值的数据记录大量存在着明显的数据分布规律或特征,例如带有缺失值的数据记录的目标标签(即分类中的 Label 变量)主要集中于某一类或几类,如果删除这些数据记录将使对应分类的数据样本丢失大量特征信息,导致模型过拟合或分类不准确。
相对丢弃而言,补全是更加常用的缺失值处理方式,通过一定的方法将缺失的数据补上,从而形成完整的数据记录对于后续的数据处理、
分析和建模至关重要。常用的补全方法包括:
· 统计法:对于数值型的数据,使用均值、加权均值、中位数等方法补足;对于分类型数据,使用类别众数最多的值补足。
· 模型法:更多时候我们会基于已有的其他字段,将缺失字段作为目标变量进行预测,从而得到最为可能的补全值。如果带有缺失值的列是数值变量,采用回归模型补全;如果是分类变量,则采用分类模型补全。
· 专家补全:对于少量且具有重要意义的数据记录,专家补足也是非常重要的一种途径。
· 其他方法:例如随机法、特殊值法、多重填补等。
某些情况下,我们可能无法得知缺失值的分布规律,并且无法对于缺失值采用上述任何一种方法做处理;或者我们认为数据缺失也是一种规律,不应该轻易对缺失值随意处理,那么还有一种缺失值处理思路—— 真值转换。
该思路的根本观点是,我们承认缺失值的存在,并且把数据缺失也作为数据分布规律的一部分,这将变量的实际值和缺失值都作为输入维度参与后续数据处理和模型计算。但是变量的实际值可以作为变量值参与模型计算,而缺失值通常无法参与运算,因此需要对缺失值进行真值转换。以用户性别字段为例,很多数据库集都无法对会员的性别进行补足,但又舍不得将其丢弃,那么我们将选择将其中的值,包括男、女、未知从一个变量的多个值分布状态转换为多个变量的真值分布状态。
· 转换前:性别(值域:男、女、未知)。
· 转换后:性别 _ 男(值域 1 或 0 )、性别 _ 女(值域 1 或 0 )、性别 _ 未知(值域 1 或 0 )。
在数据预处理阶段,对于具有缺失值的数据记录不做任何处理,也是一种思路。这种思路主要看后期的数据分析和建模应用,很多模型对于缺失值有容忍度或灵活的处理方法,因此在预处理阶段可以不做处理。常见的能够自动处理缺失值的模型包括: KNN 、决策树和随机森林、神经网络和朴素贝叶斯、 DBSCAN (基于密度的带有噪声的空间聚类)等。这些模型对于缺失值的处理思路是:
· 忽略,缺失值不参与距离计算,例如 KNN 。
· 将缺失值作为分布的一种状态,并参与到建模过程,例如各种决策树及其变体。
· 不基于距离做计算,因此基于值的距离做计算,本身的影响就消除,例如 DBSCAN 。
在数据建模前的数据归约阶段,有一种归约的思路是降维,降维中又有一种直接选择特征的方法。假如我们通过一定方法确定带有缺失值(无论缺少字段的值缺失数量有多少)的字段对于模型的影响非常小,那么我们根本就不需要对缺失值进行处理。因此,后期建模对
字段或特征的重要性判断也是决定是否处理字段缺失值的重要参考因素之一。对于缺失值的处理思路是先通过一定方法找到缺失值,接着分析缺失值在整体样本中的分布占比以及缺失值是否具有显著的无规律分布特征,然后考虑后续要使用的模型中是否能满足缺失值的自动处理,最后决定采用哪种缺失值处理方法。在选择处理方法时,注意投入的时间、精力和产出价值,毕竟,处理缺失值只是整个数据工作的冰山一角而已。
异常数据是数据分布的常态,处于特定分布区域或范围之外的数据通常会被定义为异常或 “ 噪音 ” 。产生数据 “ 噪音 ” 的原因很多,例如业务运营操作、数据采集问题、数据同步问题等。对异常数据进行处理前,需要先辨别出到底哪些是真正的数据异常。从数据异常的状态看分为两种:
· 一种是 “ 伪异常 ” ,这些异常是由于业务特定运营动作产生,其实是正常反映业务状态,而不是数据本身的异常规律。
· 一种是 “ 真异常 ” ,这些异常并不是由于特定的业务动作引起的,而是客观地反映了数据本身分布异常的个案。
大多数数据挖掘或数据工作中,异常值都会在数据的预处理过程中被认为是噪音而剔除,以避免其对总体数据评估和分析挖掘的影响但
在以下几种情况下,无须对异常值做抛弃处理。
1. 异常值正常反映了业务运营结果该场景是由业务部门的特定动作导致的数据分布异常,如果抛弃异常值将导致无法正确反馈业务结果。例如:公司的 A 商品正常情况下日销量为 1000 台左右。由于昨日举行优惠促销活动导致总销量达到 10000 台,由于后端库存备货不足导致今日销量又下降到 100 台。在这种情况下, 10000 台和 100 台都正确反映了业务运营的结果,而非数据异常。
2. 异常检测模型异常检测模型是针对整体样本中的异常数据进行分析和挖掘以便找到其中的异常个案和规律,这种数据应用围绕异常值展开,因此异常值不能做抛弃处理。异常检测模型常用于客户异常识别、信用卡欺诈、贷款审批识别、药物变异识别、恶劣气象预测、网络入侵检测、流量作弊检测等。在这种情况下,异常数据本身是目标数据,如果被处理掉将损失关键信息。
3. 包容异常值的数据建模如果数据算法和模型对异常值不敏感,那么即使不处理异常值也不会对模型本身造成负面影响。例如在决策树中,异常值本身就可以作为一种分裂节点。除了抛弃和保留,还有一种思路可对异常值进行处理,例如使用其他统计量、预测量进行替换,但不推荐使用这种方法,原因是这会将其中的关键分布特征消除,从而改变原始数据集的分布规律。
3.1.3 数据重复就需要去重吗
数据集中的重复值包括以下两种情况:
· 数据值完全相同的多条数据记录。这是最常见的数据重复情况。
· 数据主体相同但匹配到的唯一属性值不同。这种情况多见于数据仓库中的变化维度表,同一个事实表的主体会匹配同一个属性的多个值。去重是重复值处理的主要方法,主要目的是保留能显示特征的唯一数据记录。但当遇到以下几种情况时,请慎重(不建议)执行数据去重。
1. 重复的记录用于分析演变规律
相关知识点:变化维度表
变化维度表是数据仓库中的概念。维度表类似于匹配表,用来存储静态的维度、属性等数据,而这些数据一般都不会改变。但是变与不变是一个相对的概念,随着企业的不断发展,很多时候维度也会发生变化。因此在某个时间内的维度是不变的,而从整体来看维度是变化的。对于维度的变化,有 3 种方式进行处理:
· 直接覆盖原有值 。这种情况下每个唯一 ID 就只对应一个属性值,这样做虽然简单粗暴也容易实现,但是无法保留历史信息。
· 添加新的维度行 。此时同一个 ID 会得到两条匹配记录。
· 增加新的属性列 。此时不会新增数据行记录,只是在原有的记录中新增一列用于标记不同时期的值。
注意:真正的变化维度表或维度表不会以中文做主键,通常都会使用数字或字符串类作为唯一关联 ID ,本节的示例仅做说明之用。
2. 重复的记录用于样本不均衡处理在开展分类数据建模工作时,样本不均衡是影响分类模型效果的关键因素之一,解决分类方法的一种方法是对少数样本类别做简单过采样,通过随机过采样采取简单复制样本的策略来增加少数类样本。经过这种处理方式后,也会在数据记录中产生相同记录的多条数据。此时,我们不能对其中重复值执行去重操作。
3. 重复的记录用于检测业务规则问题
1. 缺失值处理
对于缺失值的处理,主要配合使用 sklearn.preprocessing 中的 Imputer类、 Pandas 和 Numpy 。其中由于 Pandas 对于数据探索、分析和探查的支持较为良好,因此围绕 Pandas 的缺失值处理较为常用。
import pandas as pd # 导入 Pandas 库 import numpy as np # 导入 Numpy 库 from sklearn.preprocessing import Imputer # 导入 sklearn.preprocessing 中的Imputer 库 # 生成缺失数据 df = pd.DataFrame(np.random.randn(6, 4), columns=['col1', 'col2', 'col3', 'col4']) # 生成一份数据 df.iloc[1:2, 1] = np.nan # 增加缺失值 df.iloc[4, 3] = np.nan # 增加缺失值 print (df)
# 查看哪些值缺失 nan_all = df.isnull() # 获得所有数据框中的 N 值 print (nan_all) # 打印输出
# 查看哪些列缺失 nan_col1 = df.isnull().any() # 获得含有 NA 的列 nan_col2 = df.isnull().all() # 获得全部为 NA 的列 print (nan_col1) # 打印输出
print (nan_col2) # 打印输出
# 丢弃缺失值 df2 = df.dropna() # 直接丢弃含有 NA 的行记录 print (df2) # 打印输出
# 使用 sklearn 将缺失值替换为特定值 nan_model = Imputer(missing_values='NaN', strategy='mean', axis=0) # 建立替换规则:将值为 Nan 的缺失值用均值做替换 nan_result = nan_model.fit_transform(df) # 应用模型规则 print (nan_result) # 打印输出
#使用 Pandas 将缺失值替换为特定值 nan_result_pd1 = df.fillna(method='backfill') # 用后面的值替换缺失值 nan_result_pd2 = df.fillna(method='bfill', limit=1) # 用后面的值替换缺失值 , 限制每列只能替换一个缺失值 nan_result_pd3 = df.fillna(method='pad') # 用前面的值替换缺失值 nan_result_pd4 = df.fillna(0) # 用 0 替换缺失值 nan_result_pd5 = df.fillna({'col2': 1.1, 'col4': 1.2}) # 用不同值替换不同列的缺失值 nan_result_pd6 = df.fillna(df.mean()['col2':'col4']) # 用平均数代替 , 选择各自列的均值替换缺失值 # 打印输出 print (nan_result_pd1) # 打印输出 print (nan_result_pd2) # 打印输出 print (nan_result_pd3) # 打印输出 print (nan_result_pd4) # 打印输出 print (nan_result_pd5) # 打印输出 print (nan_result_pd6) # 打印输出
有关异常值的确定有很多规则和方法,这里使用 Z 标准化得到的阈值作为判断标准:当标准化后的得分超过阈值则为异常。完整代码如下:
import pandas as pd # 导入 Pandas 库 # 生成异常数据 df = pd.DataFrame({'col1': [1, 120, 3, 5, 2, 12, 13], 'col2': [12, 17, 31, 53, 22, 32, 43]}) print (df) # 打印输出
# 通过 Z-Score 方法判断异常值 df_zscore = df.copy() # 复制一个用来存储 Z-score 得分的数据框 cols = df.columns # 获得数据框的列名 for col in cols: # 循环读取每列 df_col = df[col] # 得到每列的值 z_score = (df_col - df_col.mean()) / df_col.std() # 计算每列的 Z-score 得分 df_zscore[col] = z_score.abs() > 2.2 # 判断 Z-score 得分是否大于 2.2 ,如果是则为 True ,否则为 False print (df_zscore) # 打印输出
主要需要考虑的关键点是:如何判断异常值。对于有固定业务规则的可直接套用业务规则,而对于没有固定业务规则的,可以采用常见的数学模型进行判断,即基于概率分布的模型(例如正态分布的标准差范围)、基于聚类的方法(例如 KMeans )、基于密度的方法(例如 LOF )、基于分类的方法(例如 KNN )、基于统计的方法(例如分位数法)等,此时异常值的定义带有较强的主观判断色彩,具体需要根据实际情况选择。
有关重复值的处理代码示例如下:
import pandas as pd # 导入 Pandas 库 # 生成重复数据 data1 = ['a', 3] data2 = ['b', 2] data3 = ['a', 3] data4 = ['c', 2] df = pd.DataFrame([data1, data2, data3, data4], columns=['col1', 'col2']) print (df)
# 判断重复数据 isDuplicated = df.duplicated() # 判断重复数据记录 print (isDuplicated) # 打印输出
# 删除重复值 new_df1 = df.drop_duplicates() # 删除数据记录中所有列值相同的记录 new_df2 = df.drop_duplicates(['col1']) # 删除数据记录中 col1 值相同的记录 new_df3 = df.drop_duplicates(['col2']) # 删除数据记录中 col2 值相同的记录 new_df4 = df.drop_duplicates(['col1', 'col2']) # 删除数据记录中指定列( col1/col2 )值相同的记录 print (new_df1) # 打印输出
print (new_df2) # 打印输出
print (new_df3) # 打印输出
print (new_df4) # 打印输出
判断方法为 df.duplicated (),该方法中两个主要的参数是 subset 和 keep :
·subset :要判断重复值的列,可以指定特定列或多个列。默认使用全部列。
·keep :当重复时不标记为 True 的规则,可设置为第一个( first )、最后一个( last )和全部标记为 True ( False )。默认使用 first ,即第一个重复值不标记为 True 。除了 Pandas 可用来做重复值判断和处理外,也可以使用 Numpy 中的unique ()方法,该方法返回其参数数组中所有不同的值,并且按照从小到大的顺序排列。 Python 自带的内置函数 set 方法,也能返回唯一元素的集合。
主要用了几个知识点:
· 通过 pd.DataFrame 新建数据框;
· 通过 df.iloc[] 来选择特定的列或对象;
· 使用 Pandas 的 isnull ()判断值是否为空;
· 使用 all ()和 any ()判断每列是否包含至少 1 个为 True 或全部为True 的情况;
· 使用 Pandas 的 dropna ()直接删除缺失值;
· 使用 Sklearn.preprocessing 中的 Imputer 方法对缺失值进行填充和替换,支持 3 种填充方法;
· 使用 Pandas 的 fillna 填充缺失值,支持更多自定义的值和常用预定义方法;
· 通过 copy ()获得一个对象副本,常用于原始对象和复制对象同时进行操作的场景;
· 通过 for 循环遍历可迭代的列表值;
· 自定义了 Z-Score 计算公式;
· 通过 Pandas 的 duplicated ()判断重复数据记录;
· 通过 Pandas 的 drop_duplicates ()删除数据记录,可指定特定列或全部。
Sed ac lorem felis. Ut in odio lorem. Quisque magna dui, maximus ut commodo sed, vestibulum ac nibh. Aenean a tortor in sem tempus auctor
December 4, 2020 at 3:12 pm
Sed ac lorem felis. Ut in odio lorem. Quisque magna dui, maximus ut commodo sed, vestibulum ac nibh. Aenean a tortor in sem tempus auctor
December 4, 2020 at 3:12 pm
Donec in ullamcorper quam. Aenean vel nibh eu magna gravida fermentum. Praesent eget nisi pulvinar, sollicitudin eros vitae, tristique odio.
December 4, 2020 at 3:12 pm
我是 s enim interduante quis metus. Duis porta ornare nulla ut bibendum
Rosie
6 minutes ago