掌握 Python 数据清理的艺术 - KDnuggets

掌握 Python 数据清理的艺术 – KDnuggets

源节点: 2939047

掌握 Python 数据清理的艺术
图片作者
 

数据清理是任何数据分析过程的关键部分。 在此步骤中,您将删除错误、处理丢失的数据并确保数据采用您可以使用的格式。 如果没有经过良好清理的数据集,任何后续分析都可能会出现偏差或不正确。

本文向您介绍了使用 pandas、numpy、seaborn 和 matplotlib 等功能强大的库在 Python 中进行数据清理的几种关键技术。

在深入研究数据清理机制之前,让我们先了解其重要性。 现实世界的数据通常是混乱的。 它可能包含重复条目、不正确或不一致的数据类型、缺失值、不相关的特征和异常值。 所有这些因素在分析数据时都可能导致误导性的结论。 这使得数据清理成为数据科学生命周期中不可或缺的一部分。

我们将介绍以下数据清理任务。
 

掌握 Python 数据清理的艺术
图片作者

在开始之前,让我们导入必要的库。 我们将使用 pandas 进行数据操作,使用 seaborn 和 matplotlib 进行可视化。

我们还将导入 datetime Python 模块来操作日期。

import pandas as pd
import seaborn as sns
import datetime as dt
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker

首先,我们需要加载数据。 在此示例中,我们将使用 pandas 加载 CSV 文件。 我们还添加分隔符参数。

df = pd.read_csv('F:KDNuggetsKDN Mastering the Art of Data Cleaning in Pythonproperty.csv', delimiter= ';')

接下来,检查数据以了解其结构、我们正在使用什么类型的变量以及是否存在缺失值非常重要。 由于我们导入的数据并不大,让我们看一下整个数据集。

# Look at all the rows of the dataframe
display(df)

数据集如下所示。

 

掌握 Python 数据清理的艺术
 

您可以立即看到有一些缺失值。 另外,日期格式不一致。

现在,让我们使用 info() 方法查看 DataFrame 摘要。

# Get a concise summary of the dataframe
print(df.info())

这是代码输出。

 

掌握 Python 数据清理的艺术
 

我们可以看到只有 square_feet 列没有任何 NULL 值,所以我们必须以某种方式处理这个问题。 此外,广告日期和销售日期列是对象数据类型,即使这应该是日期。

列位置完全是空的。 我们需要它吗?

我们将向您展示如何处理这些问题。 我们将从学习如何删除不必要的列开始。

数据集中有两列我们在数据分析中不需要,因此我们将删除它们。

第一栏是买家。 我们不需要它,因为买家的姓名不会影响分析。

我们使用带有指定列名的 drop() 方法。 我们将轴设置为 1 以指定我们要删除一列。 此外,inplace 参数设置为 True,以便我们修改现有的 DataFrame,并且不会在没有删除的列的情况下创建新的 DataFrame。

df.drop('buyer', axis = 1, inplace = True)

我们要删除的第二列是位置。 虽然拥有此信息可能很有用,但这是一个完全空的列,因此我们将其删除。

我们采用与第一列相同的方法。

df.drop('location', axis = 1, inplace = True)

当然,您可以同时删除这两列。

df = df.drop(['buyer', 'location'], axis=1)

两种方法都会返回以下数据帧。

 

掌握 Python 数据清理的艺术

由于各种原因,数据集中可能会出现重复数据,并且可能会影响您的分析。

让我们检测数据集中的重复项。 以下是具体操作方法。

下面的代码使用了该方法 重复的() 考虑整个数据集中的重复项。 其默认设置是将第一次出现的值视为唯一,将后续出现的值视为重复。 您可以使用以下命令修改此行为 保持 范围。 例如, df.duplicate(keep=False) 会将所有重复项标记为 True,包括第一次出现。

# Detecting duplicates
duplicates = df[df.duplicated()]
duplicates

这是输出。

 

掌握 Python 数据清理的艺术
 

索引为 3 的行已被标记为重复,因为具有相同值的行 2 是其第一次出现。

现在我们需要删除重复项,我们使用以下代码来完成此操作。

# Detecting duplicates
duplicates = df[df.duplicated()]
duplicates

drop_duplicates() 函数在识别重复项时考虑所有列。 如果您只想考虑某些列,可以将它们作为列表传递给此函数,如下所示:df.drop_duplicates(subset=['column1', 'column2'])。

 

掌握 Python 数据清理的艺术
 

如您所见,重复的行已被删除。 但是,索引保持不变,但缺少索引 3。 我们将通过重置索引来解决这个问题。

df = df.reset_index(drop=True)

该任务是通过使用 重置索引() 功能。 drop=True 参数用于丢弃原始索引。 如果不包含此参数,旧索引将作为新列添加到 DataFrame 中。 通过设置 drop=True,您告诉 pandas 忘记旧索引并将其重置为默认整数索引。

为了练习,尝试 从此 Microsoft 数据集中删除重复项.

有时,数据类型可能设置不正确。 例如,日期列可能会被解释为字符串。 您需要将它们转换为适当的类型。

在我们的数据集中,我们将对广告日期和销售日期列执行此操作,因为它们显示为对象数据类型。 此外,各行的日期格式也不同。 我们需要使其保持一致,并将其转换为最新的。

最简单的方法是使用 to_datetime() 方法。 同样,您可以逐列执行此操作,如下所示。

执行此操作时,我们将 dayfirst 参数设置为 True,因为某些日期首先从天开始。

# Converting advertisement_date column to datetime
df['advertisement_date'] = pd.to_datetime(df['advertisement_date'], dayfirst = True) # Converting sale_date column to datetime
df['sale_date'] = pd.to_datetime(df['sale_date'], dayfirst = True)

您还可以使用以下命令同时转换两列 应用() 方法与 to_datetime().

# Converting advertisement_date and sale_date columns to datetime
df[['advertisement_date', 'sale_date']] = df[['advertisement_date', 'sale_date']].apply(pd.to_datetime, dayfirst = True)

两种方法都会给出相同的结果。

 

掌握 Python 数据清理的艺术
 

现在日期的格式是一致的。 我们看到并非所有数据都已转换。 Advertising_date 中有一个 NaT 值,sale_date 中有两个 NaT 值。 这意味着日期丢失。

让我们检查一下列是否已使用以下命令转换为日期: 信息() 方法。

# Get a concise summary of the dataframe
print(df.info())

 

掌握 Python 数据清理的艺术
 

如您所见,两列都不是 datetime64[ns] 格式。

现在,尝试将数据从 TEXT 转换为 NUMERIC Airbnb 数据集.

现实世界的数据集通常存在缺失值。 处理丢失的数据至关重要,因为某些算法无法处理此类值。

我们的示例也有一些缺失值,因此让我们看一下处理缺失数据的两种最常用方法。

删除含有缺失值的行

如果与观测总数相比,缺失数据的行数微不足道,您可以考虑删除这些行。

在我们的示例中,最后一行除了平方英尺和广告日期之外没有任何值。 我们不能使用这样的数据,所以让我们删除这一行。

这是我们指示行索引的代码。

df = df.drop(8)

DataFrame 现在看起来像这样。

 

掌握 Python 数据清理的艺术
 

最后一行已被删除,我们的 DataFrame 现在看起来更好了。 但是,仍然存在一些缺失的数据,我们将使用另一种方法来处理。

估算缺失值

如果您有大量缺失数据,比删除更好的策略可能是插补。 此过程涉及根据其他数据填充缺失值。 对于数值数据,常见的插补方法涉及使用集中趋势的度量(平均值、中位数、众数)。

在我们已经更改的 DataFrame 中,advertisement_date 和 sale_date 列中有 NaT(不是时间)值。 我们将使用以下方法来估算这些缺失值 意思() 方法。

该代码使用 填充() 方法查找空值并用平均值填充。

# Imputing values for numerical columns
df['advertisement_date'] = df['advertisement_date'].fillna(df['advertisement_date'].mean())
df['sale_date'] = df['sale_date'].fillna(df['sale_date'].mean())

您也可以在一行代码中完成相同的操作。 我们使用 应用() 应用使用定义的函数 拉姆达。 与上面相同,该函数使用 填充()意思() 方法来填补缺失值。

# Imputing values for multiple numerical columns
df[['advertisement_date', 'sale_date']] = df[['advertisement_date', 'sale_date']].apply(lambda x: x.fillna(x.mean()))

两种情况下的输出如下所示。

 

掌握 Python 数据清理的艺术
 

我们的 sale_date 列现在包含我们不需要的时间。 让我们删除它们。

我们将使用 时间() 方法,它将日期转换为其字符串表示形式和特定格式。

df['sale_date'] = df['sale_date'].dt.strftime('%Y-%m-%d')

 

掌握 Python 数据清理的艺术
 

现在日期看起来都很整齐。

如果您需要使用 时间() 在多列上,您可以再次使用 拉姆达 以下方式。

df[['date1_formatted', 'date2_formatted']] = df[['date1', 'date2']].apply(lambda x: x.dt.strftime('%Y-%m-%d'))

现在,让我们看看如何估算缺失的分类值。

分类数据是一种用于对具有相似特征的信息进行分组的数据类型。 这些组中的每一个都是一个类别。 分类数据可以采用数值(例如“1”表示“男性”,“2”表示“女性”),但这些数字没有数学意义。 例如,您不能将它们加在一起。

分类数据通常分为两类:

  1. 标称数据: 这是当类别仅被标记并且不能以任何特定顺序排列时。 例如,性别(男性、女性)、血型(A、B、AB、O)或颜色(红、绿、蓝)。
  1. 序数数据: 此时可以对类别进行排序或排名。 虽然类别之间的间隔不是等距的,但类别的顺序是有意义的。 例如,评级量表(电影的 1 到 5 级)、教育水平(高中、本科、研究生)或癌症分期(第一期、第二期、第三期)。

为了估算缺失的分类数据,通常使用该模式。 在我们的示例中,列 property_category 是分类(名义)数据,并且两行中缺少数据。

让我们用众数替换缺失值。

# For categorical columns
df['property_category'] = df['property_category'].fillna(df['property_category'].mode()[0])

这段代码使用了 填充() 函数替换 property_category 列中的所有 NaN 值。 它用模式替换它。

此外,[0] 部分用于从该系列中提取第一个值。 如果有多种模式,将选择第一个。 如果只有一种模式,它仍然可以正常工作。

这是输出。

 

掌握 Python 数据清理的艺术
 

现在看来数据还不错。 唯一剩下的就是看看是否有异常值。

您可以在此练习处理空值 元面试问题,您必须将 NULL 替换为零。

离群值是数据集中与其他观察结果明显不同的数据点。 它们可能与数据集中的其他值相距甚远,位于整体模式之外。 它们被认为是不寻常的,因为它们的值与其他数据相比要么显着更高或更低。

异常值可能由于多种原因而出现,例如:

  • 测量或输入错误
  • 数据损坏
  • 真实的统计异常

异常值会显着影响数据分析和统计建模的结果。 它们可能导致偏斜分布、偏差或使基础统计假设无效、扭曲估计模型拟合、降低预测模型的预测准确性并导致错误的结论。

检测异常值的一些常用方法包括 Z 分数、IQR(四分位距)、箱线图、散点图和数据可视化技术。 在一些高级案例中,还使用机器学习方法。

可视化数据可以帮助识别异常值。 Seaborn 的箱线图对此很方便。

plt.figure(figsize=(10, 6))
sns.boxplot(data=df[['advertised_price', 'sale_price']])

我们使用 plt.figure() 设置图形的宽度和高度(以英寸为单位)。

然后我们为广告价格和销售价格列创建箱线图,如下所示。

 

掌握 Python 数据清理的艺术
 

通过将其添加到上面的代码中,可以改进该图以便于使用。

plt.xlabel('Prices')
plt.ylabel('USD')
plt.ticklabel_format(style='plain', axis='y')
formatter = ticker.FuncFormatter(lambda x, p: format(x, ',.2f'))
plt.gca().yaxis.set_major_formatter(formatter)

我们使用上面的代码来设置两个轴的标签。 我们还注意到 y 轴上的值采用科学计数法,我们不能将其用于价格值。 因此,我们使用 plt.ticklabel_format() 函数将其更改为普通样式。

然后我们创建格式化程序,它将在 y 轴上显示值,并用逗号作为千位分隔符和小数点。 最后一行代码将其应用于轴。

现在的输出看起来像这样。

 

掌握 Python 数据清理的艺术
 

现在,我们如何识别并消除异常值?

其中一种方法是使用 IQR 方法。

IQR(即四分位数范围)是一种统计方法,用于通过将数据集划分为四分位数来测量变异性。 四分位数将按排名排序的数据集分为四个相等的部分,第一个四分位数(第 25 个百分位数)和第三个四分位数(第 75 个百分位数)范围内的值构成四分位数范围。

四分位距用于识别数据中的异常值。 它的工作原理如下:

  1. 首先,计算第一个四分位数(Q1)、第三个四分位数(Q3),然后确定 IQR。 IQR 计算为 Q3 – Q1。
  2. 任何低于 Q1 – 1.5IQR 或高于 Q3 + 1.5IQR 的值均被视为异常值。

在我们的箱线图上,箱线实际上代表 IQR。 框内的线是中位数(或第二个四分位数)。 箱线图的“须线”表示 Q1.5 和 Q1 的 3*IQR 范围内的范围。

这些胡须之外的任何数据点都可以被视为异常值。 在我们的例子中,其价值为 12,000,000 美元。 如果您查看箱线图,您会发现其表示得多么清晰,这说明了为什么数据可视化对于检测异常值很重要。

现在,让我们在 Python 代码中使用 IQR 方法来删​​除异常值。 首先,我们将删除广告中的异常价格。

Q1 = df['advertised_price'].quantile(0.25)
Q3 = df['advertised_price'].quantile(0.75)
IQR = Q3 - Q1
df = df[~((df['advertised_price'] (Q1 - 1.5 * IQR)) |(df['advertised_price'] > (Q3 + 1.5 * IQR)))]

我们首先使用以下公式计算第一个四分位数(或第 25 个百分位数) 分位数() 功能。 我们对第三个四分位数或第 75 个百分位数执行相同的操作。

它们分别显示 25% 和 75% 的数据低于该值。

然后我们计算四分位数之间的差异。 到目前为止,一切只是将 IQR 步骤转换为 Python 代码。

作为最后一步,我们删除异常值。 换句话说,所有数据都小于 Q1 – 1.5 * IQR 或大于 Q3 + 1.5 * IQR。

“~”运算符否定条件,因此我们只剩下非异常值的数据。

然后我们可以对销售价格做同样的事情。

Q1 = df['sale_price'].quantile(0.25)
Q3 = df['sale_price'].quantile(0.75)
IQR = Q3 - Q1
df = df[~((df['sale_price'] (Q1 - 1.5 * IQR)) |(df['sale_price'] > (Q3 + 1.5 * IQR)))]

当然,您可以使用更简洁的方式来完成 for循环.

for column in ['advertised_price', 'sale_price']: Q1 = df[column].quantile(0.25) Q3 = df[column].quantile(0.75) IQR = Q3 - Q1 df = df[~((df[column] (Q1 - 1.5 * IQR)) |(df[column] > (Q3 + 1.5 * IQR)))]

循环迭代两列。 对于每一列,它计算 IQR,然后删除 DataFrame 中的行。

请注意,此操作是按顺序完成的,首先针对advertising_price,然后针对sale_price。 因此,DataFrame 会针对每一列进行就地修改,并且由于任一列中的异常值,行可能会被删除。 因此,与单独删除advertising_price 和 sale_price 的异常值并随后合并结果相比,此操作可能会导致更少的行数。

在我们的示例中,两种情况下的输出都是相同的。 要查看箱线图如何变化,我们需要使用与之前相同的代码再次绘制它。

plt.figure(figsize=(10, 6))
sns.boxplot(data=df[['advertised_price', 'sale_price']])
plt.xlabel('Prices')
plt.ylabel('USD')
plt.ticklabel_format(style='plain', axis='y')
formatter = ticker.FuncFormatter(lambda x, p: format(x, ',.2f'))
plt.gca().yaxis.set_major_formatter(formatter)

这是输出。

 

掌握 Python 数据清理的艺术
 

您可以通过解决以下问题来练习在 Python 中计算百分位数 大会面试问题.

数据清洗是数据分析过程中至关重要的一步。 尽管这可能很耗时,但确保结果的准确性至关重要。

幸运的是,Python 丰富的库生态系统使这个过程更易于管理。 我们学习了如何删除不必要的行和列、重新格式化数据以及处理缺失值和异常值。 这些是必须对大多数数据执行的常规步骤。 但是,有时您也需要 将两列合并为一列, 验证现有数据, 为其分配标签去掉空格.

所有这些都是数据清理,因为它允许您将杂乱的现实数据转换为结构良好的数据集,您可以放心地进行分析。 只需将我们开始的数据集与最终的数据集进行比较即可。

如果你没有看到这个结果的满足感,而且干净的数据也没有让你感到奇怪的兴奋,那么你到底在数据科学领域做什么!?
 

内特·罗西迪 是一名数据科学家和产品战略。 他也是教授分析学的兼职教授,并且是 地层划痕,一个帮助数据科学家准备面试的平台,回答来自顶级公司的真实面试问题。 与他联系 推特:StrataScratch or LinkedIn.

时间戳记:

更多来自 掘金队