【问题标题】:Apply df.where to selective columns in pandas to remove outliers in mixed data type dataset将 df.where 应用于 pandas 中的选择性列以删除混合数据类型数据集中的异常值
【发布时间】:2025-12-03 03:15:02
【问题描述】:

Python 和 pandas 新手设置数据清理管道,为机器学习准备 df。我想识别和删除异常值并替换(例如)算术平均值。

df 已被清理,以便将字符串 ('Identifiers') 的第 1 列设置为索引 (type=object),其余列纯数字并设置为浮点数。输入 df 的玩具去识别版本:

Identifiers        foo  categorical   bar  score1  score2  score3
0         bob   9.717501          1.0   2.0    34.0     4.0    44.0
1       carol  15.940285          0.0   6.0    65.0     3.0    46.0
2       alice  13.938485          0.0  32.0    55.0    18.0    68.0
3         jim   8.918572          0.0  15.0    71.0     5.0    50.0
4      nathan   9.698413          0.0   4.0    36.0    10.0    48.0

以下代码运行成功:

for col in df_pheno:
s = df_pheno.mean(axis = 0)
q = df_pheno.std (axis = 0)
r = s + (3 * q)
if col == 'Identifiers':
    continue
elif col != 'Identifiers':
    for i, row_value in df_pheno[col].iteritems():
        if row_value > r.loc[col]:
            row_value = df_pheno.replace(row_value,s.loc[col],inplace = True)
        elif row_value <= r.loc[col]:
            continue

输出(注意:在玩具示例中,条件从 r 更改为 s,但没有什么不同):

Identifiers        foo  categorical   bar  score1  score2  score3
0         bob   9.717501          0.2   2.0    34.0     4.0    44.0
1       carol  11.642651          0.0   6.0    52.2     3.0    46.0
2       alice  11.642651          0.0  11.8    52.2     8.0    51.2
3         jim   8.918572          0.0  11.8    52.2     5.0    50.0
4      nathan   9.698413          0.0   4.0    36.0     8.0    48.0

我想看看 df.where 是否加快了操作,但在各种排列中,我要么 a) 无法让它忽略“标识符”列,要么 b) 输入一个非 NaN 值。由于与管道中的下一步有关的原因,我不希望插入 NaN 然后输入非 NaN 值——如果可能的话。示例工作/问题:

for col in df_pheno:
s = df_pheno.mean(axis = 0)
q = df_pheno.std (axis = 0)
r = s + (3 * q)
if col == 'Identifiers':
    continue
elif col != 'Identifiers':
    df_pheno.where(df_pheno > r, s, inplace=True, axis=1)

TypeError: 无法对具有非 np.nan 值的混合类型进行就地布尔设置

或者:

for col in df_pheno:
s = df_pheno.mean(axis = 0)
q = df_pheno.std (axis = 0)
r = s + (3 * q)
if col == 'Identifiers':
    continue
elif col != 'Identifiers':
    df_pheno[col].where(df_pheno[col] > r, s[col], inplace=True, axis=1)

ValueError: 只能比较标签相同的 Series 对象

非常感谢任何帮助。

【问题讨论】:

  • 欢迎来到*,你能展示一个输入和输出数据框的例子吗?
  • 感谢 - 长期读者,第一次发帖。我已经编辑了问题以包含一个输入和成功输出的玩具示例。
  • 不明白为什么会有等于0.2的值

标签: python pandas dataframe outliers


【解决方案1】:

您的问题是因为 std (s)、mean 和 r 的系列没有标识符的值,但是 DataFrame 有。这就是为什么我要使用set_index('Identifiers') 并在我完成操作后使用reset_index()

在这里咨询:

DataFrame.set_indexDataFrame.reset_index


我想你只需要:

df=df_pheno.set_index('Identifiers')
m=df.mean()
s=df.std()
r=m+3*s

现在用 rms 应用 mask

df.mask(df>m,m,axis=1).reset_index()

输出:

  Identifiers        foo  categorical  bar  score1  score2  score3
0         bob  10.723134          0.0  1.0    40.0     3.0    48.0
1       carol  11.567761          0.2  0.0    34.0     2.0    43.0
2       alice  11.567761          0.0  9.2    50.4     7.6    53.8
3         jim  10.793862          0.0  9.2    50.4     3.0    48.0
4      nathan   9.633013          0.0  2.0    44.0     7.6    53.8

df.mask(df>s,s,axis=1).reset_index()

df.mask(df>r,r,axis=1).reset_index()

【讨论】:

  • 非常感谢@ansev。这完美地工作并且对您的最后一行进行微小的编辑就地工作。我没有正确考虑设置索引。之前已经这样做了,但我想是隐含地认为它适用于全局空间。