# 4.6.2 异常值检测与处理（问答库）

1. 【单选题·易】课程中，异常值是指？
   A. 数据框中完全相同的重复行
   B. 数据中偏离正常范围的极端值
   C. 用 `np.nan` 表示的缺失值
   D. 分位数恰好等于 25% 的观测
   **答案：B**
   **解析：** 语料定义：异常值是指数据中偏离正常范围的极端值，可能是由于测量错误、数据录入错误或其他原因导致的。A 是重复值，C 是缺失值，均属其他小节。

2. 【单选题·易】计算数据分位数、进而得到第一和第三四分位数时，课程使用的函数是？
   A. `mean()`
   B. `dropna()`
   C. `quantile()`
   D. `duplicated()`
   **答案：C**
   **解析：** `quantile()` 用于计算数据的分位数。`mean()` 求均值，`dropna()` 删缺失值，`duplicated()` 检测重复值。

3. 【判断题·易】四分位数范围 IQR 的计算公式是 IQR = Q3 - Q1。
   **答案：√**
   **解析：** 语料明确：IQR = Q3 - Q1。Q1、Q3 分别是第一、第三四分位数。

4. 【判断题·易】25% 和 75% 分位数分别称为第一和第三四分位数。
   **答案：√**
   **解析：** 课程说明：通过 `quantile()` 可计算 25%、75% 等常用分位数；25% 和 75% 分位数分别称为第一和第三四分位数（Q1、Q3）。

5. 【多选题·中】按课程的 IQR 规则，下列关于异常值判定的说法正确的有：
   A. 小于 `Q1 - 1.5 * IQR` 的观测视为异常值
   B. 大于 `Q3 + 1.5 * IQR` 的观测视为异常值
   C. 只要小于 Q1 或大于 Q3，就是异常值
   D. 识别异常值前需要先用 `quantile()` 求出 Q1 和 Q3
   **答案：ABD**
   **解析：** 判定区间是 `Q1 - 1.5*IQR` 与 `Q3 + 1.5*IQR` 之外，不是简单的「在 Q1、Q3 之外」。Q1、Q3 由 `quantile(0.25)`、`quantile(0.75)` 得到。

6. 【单选题·中】执行下列代码，Q1、Q3 分别对应哪两个调用？

```python
import pandas as pd
data = pd.Series([10, 12, 15, 20, 100, 25, 30, 200])
Q1 = data.quantile(0.25)
Q3 = data.quantile(0.75)
print(Q1, Q3)
```

   A. `quantile(25)` 与 `quantile(75)`
   B. `quantile(0.25)` 与 `quantile(0.75)`
   C. `quantile(1)` 与 `quantile(3)`
   D. `quantile(0.5)` 与 `quantile(1.5)`
   **答案：B**
   **解析：** 参数是 0 到 1 的比例。第一四分位数用 `0.25`，第三四分位数用 `0.75`。写成 25、75 会超出合法比例范围，得不到 Q1、Q3。

7. 【单选题·中】执行下列代码，`print` 输出的异常值列表是？

```python
import pandas as pd
data = pd.Series([10, 12, 15, 20, 100, 25, 30, 200])
Q1 = data.quantile(0.25)
Q3 = data.quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
outliers = (data < lower_bound) | (data > upper_bound)
print(data[outliers].tolist())
```

   A. `[10, 12]`
   B. `[100, 200]`
   C. `[20, 25, 30]`
   D. `[10, 12, 15, 20, 100, 25, 30, 200]`
   **答案：B**
   **解析：** 本例 Q1=14.25、Q3=47.5、IQR=33.25，下界约 -35.63、上界约 97.38。只有 100 和 200 大于上界，被标记为异常值。【例4-1】正是这组数据。

8. 【多选题·中】【例4-1】识别序列异常值并用均值替代时，下列做法正确的有：
   A. 用 `(data < lower_bound) | (data > upper_bound)` 得到布尔序列 `outliers`
   B. 用 `data[~outliers].mean()` 计算不含异常值的均值
   C. 用 `data[outliers] = mean_value` 把异常位置替换为该均值
   D. 用全部 8 个数据（含 100 和 200）的均值去替换异常值
   **答案：ABC**
   **解析：** 语料步骤：识别异常值 → 计算均值（不包含异常值）→ 用均值替换。D 把极端值算进均值，与例4-1 相反。

9. 【判断题·中】用均值替换异常值时，应当先把异常值包含进均值再替换，这样更接近原始数据的总体水平。
   **答案：×**
   **解析：** 例4-1 明确「计算均值（不包含异常值）」。若把 100、200 算进去，均值会被拉高，替换后仍受极端值影响。

10. 【单选题·难】执行下列代码，两行 `print` 的结果最接近哪一项？

```python
import pandas as pd
data = pd.Series([10, 12, 15, 20, 100, 25, 30, 200])
Q1 = data.quantile(0.25)
Q3 = data.quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
outliers = (data < lower_bound) | (data > upper_bound)
mean_value = data[~outliers].mean()
data = data.astype(float)   # 目标序列转换为浮点，保证均值可写入（新版本 pandas 要求）
data[outliers] = mean_value
print(round(mean_value, 2))
print(data.iloc[4], data.iloc[7])
```

   A. `51.5`，且第 5、第 8 个元素仍为 100 和 200
   B. `18.67`，且第 5、第 8 个元素都被替换为该均值
   C. `18.67`，但 100 和 200 被删除，序列长度变为 6
   D. `51.5`，且第 5、第 8 个元素都被替换为 51.5
   **答案：B**
   **解析：** `~outliers` 保留 10、12、15、20、25、30，均值 112/6≈18.67。`data[outliers] = mean_value` 只改 True 位置（原 100、200，即 iloc[4] 与 iloc[7]），不缩短序列。若误用全部数据求均值会得到 51.5（选项 A、D）。

11. 【简答题·中】请写出完整可运行代码：创建与【例4-1】相同的序列 `data = [10, 12, 15, 20, 100, 25, 30, 200]`，用 IQR 规则识别异常值，用不含异常值的均值替换它们，并打印处理后的数据。
   **答案：**

```python
import pandas as pd
data = pd.Series([10, 12, 15, 20, 100, 25, 30, 200])
Q1 = data.quantile(0.25)
Q3 = data.quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
outliers = (data < lower_bound) | (data > upper_bound)
mean_value = data[~outliers].mean()
data = data.astype(float)   # 目标序列转换为浮点，保证均值可写入（新版本 pandas 要求）
data[outliers] = mean_value
print("处理后的数据：")
print(data)
```

   **解析：** 评分要点：① 用序列创建该 8 个数；② `quantile(0.25)`/`quantile(0.75)` 求 Q1、Q3，IQR=Q3-Q1；③ 上下界用 1.5*IQR，布尔条件加括号并用 `|`；④ 均值用 `data[~outliers].mean()`，再布尔赋值替换。四步正确给满分。

12. 【简答题·难】结合下列代码，回答三个问题：（1）写出异常值的判定公式，并说明本例中 100、200 为何被判为异常值。（2）为什么求替换均值时要用 `data[~outliers]` 而不是 `data.mean()`？（3）`outliers` 那一行两个条件为什么必须分别加圆括号？

```python
import pandas as pd
data = pd.Series([10, 12, 15, 20, 100, 25, 30, 200])
Q1 = data.quantile(0.25)
Q3 = data.quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
outliers = (data < lower_bound) | (data > upper_bound)
mean_value = data[~outliers].mean()
data = data.astype(float)   # 目标序列转换为浮点，保证均值可写入（新版本 pandas 要求）
data[outliers] = mean_value
print(data)
```

   **答案：**
   （1）小于 `Q1 - 1.5 * IQR` 或大于 `Q3 + 1.5 * IQR` 为异常值。本例 Q1=14.25、Q3=47.5、IQR=33.25，上界约 97.38，100 与 200 都大于上界，故为异常值。
   （2）`~outliers` 取出正常值再求均值，避免极端值拉高均值。`data.mean()` 含 100、200，得到约 51.5，与例4-1「均值不包含异常值」不符。
   （3）多条件须用 `|` 组合，且每个条件都要加圆括号（同 4.2.3）。漏括号时，`|` 的优先级可能先于比较运算，得不到正确的布尔序列。
   **解析：** 评分要点：① 写出带 1.5*IQR 的判定式并指出 100、200 超上界；② 说明均值必须剔除异常值；③ 说明括号与 `|` 的必要性。三点答全给满分。
