跳至主要内容

数据清洗:掌握核心要点

数据清洗是数据科学最基础的构件之一。了解数据清洗的重要性,以及如何使用 Python 开展这一过程。
· 12分钟 阅读

使用 AI 探索

无论我们的分析或预测算法多么先进,输出质量都取决于输入数据。换句话说,“垃圾进,垃圾出”。

由于数据是所有这些流程的基础,务必投入充足时间确保数据得到适当精炼。

数据清洗是数据科学生命周期中的基石环节,其作用在发掘洞见和生成可靠答案时不可过分强调。现实世界中的数据往往是脏的,数据清洗几乎无法完全回避。

在本文中,我们将涵盖一些重要概念,如如何处理缺失值、重复值和离群值。若需更系统的指导,请务必学习我们的 Python 数据清洗或 R 数据清洗课程。

是什么导致了不干净的数据?

简而言之,数据清洗(或净化)是为数据分析做准备的过程。这可能涉及查找并删除重复和不完整记录,以及修改数据以纠正不准确记录。

肮脏或不干净的数据一直是个问题,而在过去十年中,我们目睹了数据生成的指数级增长。仅在 2020 年,全球就产生了超过 64 ZB 的数据,相当于 6.4 万亿 GB。尽管保留的不到全部数据的 2%,但这无疑加剧了已有的“脏数据”这一普遍问题。在开始数据清洗之前,了解数据最初是如何变脏的至关重要。常见来源包括:

  • 数据录入、记录或编码过程中的人为错误
  • 传感设备故障,如物联网(IoT)场景
  • 硬件或软件损坏导致的数据损坏

了解我们要清洗的脏数据的根源,有助于为施加数据质量标准打下良好基础,从而对数据集中存在的不同问题进行分类。

为什么数据清洗如此重要?

数据清洗过程很重要,因为它有助于为组织的数据清洗建立模板。正如前文所述,任何数据分析或数据科学过程都是“垃圾进,垃圾出”。若被忽视,将导致昂贵且错误的分析结果,不仅浪费时间和金钱,也浪费其他投入的资源。

什么是数据质量?

数据质量是衡量我们的数据在多大程度上适合其服务目的的定性和/或定量指标。这些衡量标准是我们评估所提供数据是否适用于目标用途的实用模板。可将这些数据质量衡量视为我们的数据必须通过的一系列度量测试,方可认为适合用于数据科学流程。

数据质量标准

  1. 准确性:一个简单的问题是——数据中包含的信息在每个细节上都被正确提供了吗?通过数据,我们试图逼近现实世界中的模式;准确性有助于界定这些逼近的真实性。
  2. 相关性:这些信息对我们的最终目标是否有实际影响?
  3. 一致性:该数据来源是否经过验证,其中的信息是否可信?例如,客户年龄为 15 岁,但婚姻状况却标注为已婚。
  4. 完整性:为实现目标,数据是否提供充分且全面?这与缺失数据常有关联,一种解决办法是调查数据来源。
  5. 统一性:假设我们有一个销售额列,但并非所有交易使用相同货币。那么就有必要将所有销售额转换为同一货币,这正是统一性要解决的问题;确保在所有系统中使用相同的计量单位来规定数据度量。

数据清洗 vs. 数据转换

区分数据清洗与数据转换很重要。数据转换是一组可帮助我们从给定数据中提取更多洞见的过程。这些过程通常会将原始数据格式转换为另一种格式,例如:

  • 编码:将分类值转换为二进制值,以便在机器学习计算中使用。图示展示了对性别列进行编码后的样子。尽管承载的信息相同,但其格式已经转换。

example of data encoding

  • 分箱:也称为分桶,此过程有助于降低小幅观测的影响/规模。它将连续值分组到各个箱(或类别)中。

Data binning example

  • 缩放:这是机器学习中常用的一种技术,帮助将不同量纲的数值标准化到固定范围。

example of data scaling

请注意,在大多数数据转换过程中,数据的原始表示会被改变。虽然仍是同一数据,但为了便于机器学习或其他用途,已通过特定技术将其转化为另一种格式。

数据清洗如何开展

要实现高质量数据,制定一套指南很重要。这些指南可称为数据清洗工作流。它们帮助我们纳入数据清洗所需的全部流程。该工作流包括:

  • 数据探索
  • 数据清洗
  • 数据验证
  • 数据清洗报告 其中部分流程也将以 Python 演示

数据探索

数据探索旨在通过对数据中各变量的深入审视来理解数据。它需要使用多种可视化与汇总技术,以恰当地揭示潜在问题。为进行有效探索,需注意以下几点:

数据语境

在清洗任何数据之前,我们必须理解数据的语境。数据语境指的是数据中所有实体的来源。它涵盖数据收集的相关情境:如何收集、在何种条件下收集,从而为数据的使用方式与用途提供洞见。

这为清洗(和分析)中“何为可接受”提供指引,使我们能够从数据中得出正确洞见。一旦清楚了解数据的采集方式/时点,接下来就需要对其进行探索。

探索性数据分析

探索性数据分析指对数据进行初步调查的关键过程,以借助汇总统计与图形化展示来发现模式、识别异常、检验假设和检查前提条件。不探索,便无发现。如果不探索数据,就难以发现其中存在的各种问题。

例如,我们有一个数据集,见此处。财政局的“滚动销售”文件列出了纽约市在过去 12 个月期间出售的税类 1、2 和 4 的房产。我们将下载并读取所提供的布朗克斯数据。

#pandas
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt

#read excel file
df = pd.read_excel("rollingsales_bronx.xls")

#preview data
df.head()

Bronx rolling sales data example

该数据框的显著问题包括:

  1. 未命名列
  2. 前三行存在缺失值

然而,在 Excel 中探索实际数据后会发现,工作簿中的实际表格要到第 4 行才开始。因此,重新读取数据并设置一些参数,指明要跳过的行以及用作表头的行:

#we read the data in again but skill 3 rows this time
df = pd.read_excel("rollingsales_bronx.xls", skiprows = 4, header = [0])

df.head()

Bronx rolling sales data example cleaned up

数据的展示方式发生了显著变化。虽然我们也可以清洗第一次导入的数据,但数据探索仅通过对 Python 导入函数做出些许修改,就帮我们节省了大量时间。

数据探索就像调查员走进犯罪现场,先被动观察一切不合常理之处;而数据清洗则是主动破案的过程。

数据清洗

数据探索通常与数据清洗过程相辅相成。当我们通过可视化、汇总或统计方法发现数据问题后,就需要修复它们。在这一阶段,数据将被删除、纠正或填补。

不一致记录

一个典型例子是表单要求填写性别,但可能出现多种格式表达同一含义,如 “M”、“m”、“Male” 或 “MALE”;又或者,本月我们卖的是 “aples”、“apples” 还是 “APPLES”。最佳识别方式可以是频率图,或列出该列的所有唯一值。对不一致记录的处理包括但不限于:

  • 将字符串转换为小写或首字母大写
  • 去除空白字符
  • 重命名列名

Python 示例:使用前面在数据探索中导入的数据集,注意列名书写不一致:

Python example dataframe

虽然这似乎不算大问题,但让列名保持一致、便于访问仍然很重要。例如,EASE-MENT 的单词之间使用了连字符(-),而其他列名之间是空格。

数据清洗的一部分就是确保一致性。我们分两步来修复:

  1. 将单词间的空格替换为下划线
  2. 转换为首字母大写格式
# Extract columns
cols = df.columns

# Create empty list for new column names
new_cols = []

# Iterate over each column name to fix issues
for column in cols:
    # Convert column name to title case
    proper_cols = column.title()
    # Replace spaces and hyphens with underscores
    proper_cols_hyphen = proper_cols.replace(" ", "_")
    clean_col = proper_cols_hyphen.replace("-", "_")
    # Append the cleaned column name to the list
    new_cols.append(clean_col)

# Display the transformed column names
new_cols

# Replace existing columns in the dataframe with the cleaned list
df.columns = new_cols

# Preview the updated dataframe
df.head()

Python example 2

数据类型与类型转换

数据类型即数据的表示形式,告诉编译器如何使用该数据。数据的表示方式决定了可对其执行的操作种类。我们来预览一下布朗克斯数据中各列的数据类型。

#data types
df.dtypes

Data Types and Type Conversion

注意:考虑我们现在可以轻松使用点号方式引用列名(df.Year_Built)。

除 Year_Built 列外,其他数据类型看起来都合适;该列应为分类型。虽然影响不大,但在汇总这些列时,很可能会把 Year_Built 包含进去。

#Fix Year_Built column
df.Year_Built = df.Year_Built.astype("str")

#Check
df.dtypes

Data Types and Type Conversion 2

缺失数据

有时某些观测(行)会存在缺失数据,有时甚至会出现整列完全缺失。那么在这种情况下我们该怎么办?忽略它吗?这就像屋顶漏水,遇到下雨就会渗漏。

不同工具对缺失值有不同表示方式,包括 NULL、空字符串、NaN、NA、#NA 等。处理缺失数据时,数据语境很重要,理解数据为何缺失至关重要。处理缺失数据的两种主要方法是:

  • 删除数据
  • 数据填补

在决定采用哪种方法之前,必须首先检查各列的缺失模式。我们将使用可视化和描述性方法进行评估。

#extract the column names
cols = df.columns

#plot a heatmap of missing values with seaborn
plt.figure(figsize = (10,5))
sns.heatmap(df[cols].isnull())

Missing Data

该图直观表明:

  • Ease_ment 中的所有值以及 Apartment_Number 中几乎所有值都缺失
  • Units 与 Square_Feet 相关列的缺失值分散存在 对于更大的数据集,此图可能并不理想。另一种方法是考察这些缺失值相对于实际数据规模的重要性。
    #Get the percentage of missing values in each column
    missing_pct = round(df.isnull().sum()/len(df) * 100, 1)
    print(missing_pct)
    

Missing Data 2

我们将删除 Ease_Ment 和 Apartment_Number 两列,然后对其余列的缺失值进行替换。

#columns with more than 30% missing values
drop_cols = missing_pct[missing_pct > 30].index
#We can drop these columns with greater than 30 percent missing values
df_new = df.drop(columns = drop_cols)

#Extract columns with mising values between 1 and 30%
replace_cols = missing_pct[(missing_pct > 0) & (missing_pct < 30)].index

#Iterate to replace missing values
for col in replace_cols:
    #if column is year built we replace with median otherwise the mean
    if col == "Year_Built":
        df_new.fillna(df_new[col].median(), inplace = True)
    else:
        mean_value = df_new[col].mean()
        df_new.fillna(mean_value, inplace = True)
df_new.isnull().sum() #preview for missing values

Missing Data 3

当然,处理缺失值的内容远不止于此,Datacamp 的 用 Python 处理缺失值课程中有更详细的介绍。不同数据集、数据类型和结构有不同需求,因此,处理缺失值并非对所有数据集都有一条清晰统一的路径。下图展示了在不同情境下应采用删除还是填补技术。

Missing Data 4

重复值

我们必须确保每条观测都只有一个可信来源。在某些情形下,可能会出现关于单个客户的多条记录,原因可能是用户重复提交表单,或录入时出现错误。无论原因如何,我们都需要构建一个单一且完整的“真相版本”。这将帮助企业确保:

  1. 不会在同一客户上重复投入时间与金钱
  2. 构建起可信且完整的真相版本,从而基于分析结果做出可靠的业务决策。

离群值

离群值是极端的数据点。它们通常是非常低或非常高的数值,与数据中的其他模式不一致,例如:

  • 一位年龄为 200 岁的客户
  • 在南极地区传感器读数为 40° 摄氏度

识别离群值 识别离群值有多种技术,可通过可视化或统计方法实现:

  1. 对数据集排序:仅通过排序数据,就能较容易地发现数据集或关注变量中的离群值。然而,该技术不适用于大型数据集,且难以一目了然地预览所有值。

  2. 可视化:使用箱线图、直方图和散点图等可视化技术,可以更容易地检测离群值。

  3. 使用 Z 分数:这是一种统计技术,假设数据服从正态分布,用于量化观测值的“异常程度”。它表示观测值相对于均值偏离的标准差数。

离群值处理流程 离群值处理是对数据中表示的离群值进行删除或替换的过程:

  1. 从数据中删除离群值:这可能涉及删除位于数据下/上 X 百分位的值。以下情形可考虑删除离群值:
  2. 当数据明显测量错误时。如前所述,一位“活跃客户”年龄为 200 岁并非有效输入,这是应删除的典型离群值。
  3. 如果离群值不改变分析结果,可以删除该离群值。当数据集中离群值数量相对于整体数据不多时,也可考虑此法。

  4. 替换离群值:将这些极端值替换为均值、中位数或众数。如果离群值数量相对于实际数据规模较大,则删除离群值会失效。注意:均值对离群值敏感,因此建议优先考虑用中位数或众数进行替换。

数据验证

完成数据清洗后,务必再次通过数据探索方法重新评估数据质量。这是为了验证清洗过程的正确性与完整性,既确保没有遗漏步骤,也确保与数据语境保持一致。

数据清洗、报告与自动化

报告包括记录清洗后的数据健康状况,以及记录清洗过程所涉及的步骤。报告确保未来遇到类似的数据清洗需求时有据可循(可复现性),从而在需要时实现流程自动化。

自动化的核心在于确保数据清洗可复现。数据清洗过程中的大量步骤由可复用脚本构成,因而在需要时只需做少量修改即可复用。

结论

我们深入讨论了数据清洗以及成功开展数据清洗项目所需考虑的全部要素。这一阶段耗时颇多,数据从业者据估计会将整个数据科学项目 60% 的时间投入其中。它是一切的基石,将在很大程度上决定数据科学项目的成果。来自不同来源的不同数据有着各自的需求,您需要据此调整流程以满足具体用例。

资源:

  • 与数据转换相关的图片截取自一个 Excel 工作簿,见此处
  • Python 笔记本可在 DataCamp Workspace 获取

主题