以下是如何使用 IQR 在数据集中查找(和删除)异常值 – 每个数据集都有问题或没有意义的点。这些点,称为异常值,可以显示数据收集过程中的问题或不代表通常发生的实际现象。以下是我在实际数据中看到的一些异常值示例……

使用 Python 通过 IQR 查找异常值:操作指南

以下是使用 IQR 在数据集中查找(和删除)异常值的方法

每个数据集都有问题或没有意义的点。这些点,称为异常值,可以显示数据收集过程中的问题或不代表通常发生的实际现象。以下是我在真实数据集中看到的一些异常值示例:

  • 传感器错误:在一个项目中,我们监控人们如何在家中使用热水(在他们知情的情况下!)。该数据集包括显示一个家庭每分钟使用 400 加仑水的数据,当时淋浴喷头的最大输出量为每分钟 2 加仑。显然,传感器报告错误。
  • 非典型行为:在同一个项目中,我们记录了持续一个多小时的阵雨。我说的不是一两次淋浴——这是其中一个家庭每天都会发生的事情。由于它如此频繁,我们确信这是真实行为,而不是传感器问题。由于典型的淋浴时间约为 10 分钟,因此我们知道此人的淋浴时间比其他人都长。

在数据分析中包含异常值会扭曲数据集并对分析结果产生负面影响。因此,确保您的数据集排除所有异常值并仅使用真实数据非常重要。

让我们谈谈如何使用 IQR(四分位距)来做到这一点。

一个谨慎的词

在详细讨论如何编写 Python 代码删除异常值之前,重要的是要提到删除异常值更像是一门艺术而不是一门科学。您需要根据项目的上下文仔细确定哪些是异常值,哪些不是。以下是使用上述异常值的几个示例:

  • 传感器错误:如果我想分析数据以了解人们如何使用热水,那么每分钟 400 加仑是一个异常值,应该丢弃。没有人真正使用了那么多水,包括它会错误地改变数据集。另一方面,如果我的研究是关于传感器的准确性和可靠性,那么这些数据点准确地表明传感器偶尔会非常不准确。这是重要的信息!
  • 非典型行为:如果我想了解人们通常如何使用热水,那么长达一小时的淋浴是一个异常值,应该被丢弃。这是非常不寻常的行为,包括它会导致我的结果与典型行为不一致。但如果我想知道人们之间的行为有多少不同,那么我需要包括非典型事件,因为这是整个研究的重点。

识别和去除异常值

考虑到这一点,识别异常值的一种常见方法是基于分析数据集的统计分布。在这种方法中,您可以确定要使用的数据范围并排除其余数据。为此,您:

1.) 确定要保留的数据范围。

2.)编写代码以删除该范围之外的数据。

这是一个基于 Python 的示例,它使用 NumPy 从数据集中排除最高和最低 5% 的数据点:

import numpy as npnp.random.seed(0)random_data = np.random.rand(100, 1)p95, p5 = np.percentile(random_data, [95, 5])print(p95, p5)print(len(random_data))random_data = random_data[random_data < p95]random_data = random_data[random_data > p5]print(len(random_data))

该代码产生以下输出:

0.9456186092221561 0.0591735876605223810090

上述代码中的第一行导入 NumPy 包以供分析过程使用。如果你想用 Python 做数据科学,我建议你非常非常熟悉 NumPy。 [0]

第二行为 NumPy 的随机化代码设置了一个种子,告诉它每次都返回相同的准随机数。 [0]

第三行创建了一个新变量 random_data,它是一个包含 0 到 1 之间的 100 个随机值的数组。

第四行是魔术开始的地方。该行调用 NumPy 百分位函数来识别第 95 个百分位和第 5 个百分位的数据值,然后将这些值存储在 p95 和 p5 变量中。这些值设置了界限,稍后将用于限制数据集。

接下来的两行是显示正在发生的事情的打印语句。第一个打印 p95 和 p5 以便您可以看到这些百分位数的值。您可以看到它们非常接近数据集上限的 95% 和 5%,在非正态数据集中,这是我们所期望的。第二个打印 random_data 的长度,表明它仍然包含最初输入的 100 个值。

以下两行都根据上面指定的界限减少数据集。第一行修改 random_data 以仅包含小于 p95 的值,下一行再次对其进行调整以仅包含大于 p5 的值。通过这种方式,数据集被缩减为仅包含数据集的第 5 个和第 95 个百分位数所设置的范围内的值。这将数据集减少到总值的 90%,相当于说明最大和最小的 5% 都是异常值。

最后一行打印了修改后的 random_data 的长度,我们可以看到它现在按预期减少到了 90 个数据点。

使用 IQR(四分位距)

为了根据百分位数限制数据集,您必须首先确定要保留的数据集范围。检查数据的一种方法是根据 IQR 对其进行限制。 IQR 是一个统计概念,描述了所有数据点在平均值四分位数或中间 50% 范围内的分布。当人们想要检查人群的中间群体在做什么时,通常使用 IQR。例如,我们经常看到 IQR 用于了解学校的 SAT 或州标准化考试成绩。

使用 IQR 删除异常值时,您将删除所有位于四分位数 +/- 1.5 * IQR 定义的范围之外的点。例如,考虑以下计算。

quartile_1 = 0.45quartile_3 = 0.55IQR = 0.1lower_bound = 0.45–1.5 * 0.1 = 0.3upper_bound = 0.55 + 1.5 * 0.1 = 0.7

以下代码显示了使用 IQR 识别和删除异常值的示例。

import numpy as npnp.random.seed(0)random_data = np.random.standard_normal(100000)q3, q1 = np.percentile(random_data, [75, 25])print(q3, q1)print(len(random_data))IQR = q3 — q1print(IQR)upper_bound = q3 + 1.5 * IQRlower_bound = q1–1.5 * IQRprint(upper_bound)print(lower_bound)random_data = random_data[random_data < upper_bound]random_data = random_data[random_data > lower_bound]print(len(random_data))

它返回以下输出:

0.6734387006684548 -0.66864169618143671000001.34208039684989132.686559295943292-2.681762291456273899249

使用 IQR 拒绝异常值的代码与前面的示例代码在以下方面有所不同:

  • 使用标准正态分布创建一个包含 100,000 个值的数组。我进行了此更改以确保数据集将包含 IQR 定义的一些异常值。
  • 百分位数已从 95 和 5 更改为 75 和 25。此更改计算的是四分位数的值,而不是更极端的百分位数。
  • p95 和 p5 已重命名为 q3 和 q1,表明它们不再跟踪第 95 和第 5 个百分位数,而是跟踪第 1 个和第 3 个四分位数。
  • IQR 是通过从 q3 中减去 q1 来计算的,并打印出来以便您可以看到计算出的 IQR。
  • 该代码将上限和下限计算为 1.5 * IQR 超出第一和第三四分位数,然后打印这些界限。
  • 然后,代码将 random_data 限制为使用此方法定义的上限和下限内的所有点,而不是使用 95 和 5 个百分位数定义的所有点。

输出显示代码遵循与新要求相同的过程。它打印出第三个四分位数约为 0.68,而第一个四分位数约为 -0.67。鉴于 NumPy 的 standard_normal 函数使用标准差 1,这些数字几乎完全符合预期。然后代码打印出总数据集包含 100,000 个点。 IQR 标识为 1.34,这导致上限和下限分别为 2.69 和 -2.68。将代码过滤为仅在这两个阈值内的值会产生一个包含 99,249 个点的数据集,这表明 751 个点超出了该范围并被删除。

这就是你的做法!您现在可以考虑如何通过实用和统计方法来识别异常值,如何编写通用代码来删除异常值以及如何使用常见的四分位间距度量来评估您的数据集。