多数数据科学 机器学习项目都遵循帕累托原理,即我们用将近80%的时间进行数据准备,其余20%的时间用于选择和训练合适的机器学习模型。来源: 数据科学DataScience
通常,我们用于创建机器学习模型的数据集是混乱的,无法直接在模型中使用。我们需要确保输入到模型中的数据都是规整的数据,这就需要执行一些数据清理步骤以获得可以拟合到模型中的数据集。实际上,机器学习/数据科学项目的第一步正是数据的清洗与整理,而且在面对新的项目和问题时,我们往往需要多次重复数据清理过程。可以说数据清理是数据科学家在对数据执行任何EDA(探索性数据分析)或统计分析之前执行的最重要且耗时的过程之一。
1、什么是Tidy Data?
Tidy data(规整数据)是为了可以方便地查看数据和将数据应用在模型中而进行数据清理过程的产物。数据规整的原则定义了一些在执行数据清理操作时需要遵循的准则,从而有助于我们进行数据分析。 它提供了一种标准的方法来组织数据集中的数据值,并使我们定义数据集的方式形式化。 而且,规整数据使数据处理过程更容易。与数据库规范化形式(1NF,2NF,3NF和BCNF)一样,规整数据原则具有一些预定义的规则。
2、整洁数据原则
规整数据的原则包括:
每列代表数据集中的一个单独变量
每行代表数据集中的单个观察值
每种观察单位组成一个表格 (这些原则等效于数据库第三范式,3NF)。
接下来让我们看一些现实的数据集示例,以更详细地了解规整数据的原则。
3、每列代表一个单独变量
假设我们有一个存储每位员工的每日冰淇淋销售数据数据集, 单击此处下载冰淇淋销售示例csv文件,内容如下图所示。
这样的数据在报告中展示是十分友好的,但在分析过程中并不好用。数据中每天(周一至周日)的数据作为单独的变量用一列表示出来,但是按照规整数据原则的第一条(每列代表数据集中的一个单独变量), 我们需要将日期名称转置为一列,因为所有日期列其实代表的是同一个变量–日期。
我们可以使用pandas.melt将日期名称列转换为单列值的方法,这将帮助我们将凌乱的数据集转换为规整数据集。具体代码如下所示:
# 导入pandas库
import pandas as pd
# 使用pandas.read_csv方法 读取每位员工每日冰淇淋销售数据的csv文件
df = pd.read_csv('./Day wise Ice-cream sale detail (in dollars).csv')
'''
使用pandas.melt方法将日期名称转置为一列,完成数据由宽格式向长格式的转换,通过结果您将更好理解这里的转换
其中frame参数传入原始数据框df
id_vars参数传入用作标识符变量的列'EmployeeName'
value_vars参数传入需要取消透视的所有列,未指定情况下使用未设置为id_vars的所有列
var_name参数传入被用作“变量”列的名称
values_name参数传入被用作“值”列的名称
'''
dfMelted = pd.melt(frame = df,
id_vars = 'EmployeeName',
value_vars = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
var_name = 'WeekDay',
value_name = 'AmountInDollars')
# 打印出转换后的规整数据集前十行
print(dfMelted[:10])
4、每行代表单个观察值
假设我们有几个城市的天气数据,每个日期下都有最低和最高温度的详细信息, 单击此处下载城市气温示例csv文件,内容如下图所示。
这个数据集主要有两个问题:
(1)单一变量“日期”的值分布在不同列上,在分析过程中要在不同列中移动;
(2)置于行中的最低和最高温度值需要作为单独的列进行转置,因为它们其实代表两个不同的变量-–最低和最高温度。
要解决这些问题,我们可以先使用pandas.melt方法将日期值移动到行中, 然后使用数据透视表pivot或者pivot_table方法将最低和最高温度值作为数据集中的独立列。具体代码如下所示:
# 使用pandas.read_csv方法 读取每位员工每日冰淇淋销售数据的csv文件
df = pd.read_csv('./Date wise weather data.csv')
# pandas.melt方法将日期值转换为一列,各参数含义如第一部分所示
dfMelted = pd.melt(frame = df,
id_vars = ['CityName', 'VarType'],
value_vars = ['01-08-2018', '02-08-2018', '03-08-2018', '04-08-2018', '05-08-2018', '06-08-2018', '07-08-2018'],
var_name = 'Date',
value_name = 'Temperature')
# 打印出前十行以供参考
print('dfMelted:\n',dfMelted[:10])
'''pivot_table方法将最低和最高温度行转化为独立的列。
我们也可以使用python方法链接技术在一行代码中执行融合melt和旋转pivot,如pd.melt(...).pivot_table(...)。
这里我们使用新的数据框来保存数据透视输出,以便于理解。
index参数传入不需要转置CityName和Date列作为索引
columns参数传入需要转换的VarType列
values参数传入温度值Temperate列
'''
dfPivoted = dfMelted.pivot_table(index = ['CityName', 'Date'],
columns = 'VarType',
values = 'Temperature')
'''
由于我们传入CityName和Date列作为多级索引列,因此这两个列都将用作数据框索引列。
可以使用pandas.reset_index方法(无任何索引值)将索引重置为常规列。
Inplace参数值设置为True,以就地转换数据框,而不是创建新的数据框。
'''
dfPivoted.reset_index(inplace = True)
# 将列名称VarType重置为空
dfPivoted.columns.name = ''
# 打印分隔符与转换后的规整数据前十行
print('\ndfPivoted:\n',dfPivoted[:10])
5、每种观察组成一个表格
按照规整数据的原则,每种类型的观察单位组成一个表格,因此当一种类型的观测分布在多个文件或表格中时需要将其合并为一个表。
假设我们有两个含有日期列的csv文件,内容如下图所示,单击此处下载示例文件。
我们可以使用pandas库中concat、merge、join等方法完成两个或多个数据表向规整数据的转换。具体代码如下所示:
# 导入两个含有相同观测的csv文件
dfIceCreamSale = pd.read_csv('./Date-wise ice-cream sale detail.csv')
dfTempDetail = pd.read_csv('./Date-wise temperature detail.csv')
# pandas.merge中left、right参数分别传入含有同名列的数据框,on参数传入进行合并的列名
dfMain = pd.merge(left = dfIceCreamSale, right = dfTempDetail, on = 'Date')
# 打印合并后的规整数据集
print('Merge method:\n', dfMain)
# concat与join方法
print('\nConcat method:\n', pd.concat([dfIceCreamSale.set_index('Date'), dfTempDetail.set_index('Date')], axis=1).reset_index())
print('\nJoin method:\n',dfIceCreamSale.set_index('Date').join(dfTempDetail.set_index('Date')).reset_index(