繁体   English   中英

基于多列条件过滤熊猫数据框行

[英]Filtering pandas dataframe rows based on a multiple column condition

import pandas as pd

data = {'side':['a', 'a', 'a', 'b', 'a', 'a', 'a', 'b', 'b', 'a'],
        'price':[10400, 10400, 10400, 10380, 1041, 10400, 1041, 10400, 10399, 10399],
        'b_d100_v':[1, 1, 1, 0.3, 10, 10, 10, 10, 9, 9],
        'b_d100_p':[10390, 10391, 10390, 10390, 10390.5, 10385, 10385, 10386, 10387, 10387],
        'a_d052_v':[11, 11, 11, 9.3, 0.1, 0.1, 0.1, 0.1, 0.2, 0.3],
        'a_d052_p':[10399, 10403, 10400, 10401, 1041, 1041, 10400, 10400, 10402, 10404]
        }
df = pd.DataFrame(data, index=[101, 102, 102, 104, 105, 106, 107, 107, 107, 107])

print(df)
    side  price  b_d100_v  b_d100_p  a_d052_v  a_d052_p
101    a  10400       1.0   10390.0      11.0     10399
102    a  10400       1.0   10391.0      11.0     10403
102    a  10400       1.0   10390.0      11.0     10400
104    b  10380       0.3   10390.0       9.3     10401
105    a   1041      10.0   10390.5       0.1      1041  # Row to delete (outlier 1041 on 'price' and 'a_d052_p' columns)
106    a  10400      10.0   10385.0       0.1      1041  # Row to delete (outlier 1041 on 'a_d052_p' column)
107    a   1041      10.0   10385.0       0.1     10400  # Row to delete (outlier 1041 on 'price' column)
107    b  10400      10.0   10386.0       0.1     10400
107    b  10399       9.0   10387.0       0.2     10402
107    a  10399       9.0   10387.0       0.3     10404

我想删除仅在“价格”、“b_d100_p”和“a_d052_p”列上包含异常值的行。 为此,我选择使用基于标准偏差的条件。 这是我试过的代码。

row_with_potential_outliers = ['price', 'b_d100_p', 'a_d052_p']
df = df[abs((df[row_with_potential_outliers] - df[row_with_potential_outliers].mean()) / df[row_with_potential_outliers].std()) < 1.5]  # The value '1.5' here is arbitrary, and does not matter too much

print(df)
    side    price  b_d100_v  b_d100_p  a_d052_v  a_d052_p
101  NaN  10400.0       NaN   10390.0       NaN   10399.0
102  NaN  10400.0       NaN   10391.0       NaN   10403.0
102  NaN  10400.0       NaN   10390.0       NaN   10400.0
104  NaN  10380.0       NaN   10390.0       NaN   10401.0
105  NaN      NaN       NaN   10390.5       NaN       NaN  # Row to delete (outlier 1041 on 'price' and 'a_d052_p' columns)
106  NaN  10400.0       NaN   10385.0       NaN       NaN  # Row to delete (outlier 1041 on 'a_d052_p' column)
107  NaN      NaN       NaN   10385.0       NaN   10400.0  # Row to delete (outlier 1041 on 'price' column)
107  NaN  10400.0       NaN   10386.0       NaN   10400.0
107  NaN  10399.0       NaN   10387.0       NaN   10402.0
107  NaN  10399.0       NaN   10387.0       NaN   10404.0

如何保留“side”、“b_d100_v”和“a_d052_v”列的原始值? 这将允许我然后应用 'dropna()' 来实现我的目的......或者也许有更好的解决方案? 我使用具有数百列和数千行的数据帧,因此出于性能原因,我希望尽可能避免迭代。 在此先感谢您的帮助。

首先,要使用专有名称,请使用列设置列表名称以检查cols_to_check

cols_to_check = ['price', 'b_d100_p', 'a_d052_p']

请注意,尚未找到具有异常值的 您仅指定要检查异常值的

然后定义一个函数来查找特定列中的异常值,给定阈值:

def isOutlier(col, thr):
    return ((col - col.mean()) / col.std()).abs() > thr

要删除带有异常值的行,请运行:

df = df[~df[cols_to_check].apply(isOutlier, thr=1.5).any(axis=1)]

结果是:

    side  price  b_d100_v  b_d100_p  a_d052_v  a_d052_p
101    a  10400       1.0   10390.0      11.0     10399
102    a  10400       1.0   10391.0      11.0     10403
102    a  10400       1.0   10390.0      11.0     10400
104    b  10380       0.3   10390.0       9.3     10401
107    b  10400      10.0   10386.0       0.1     10400
107    b  10399       9.0   10387.0       0.2     10402
107    a  10399       9.0   10387.0       0.3     10404

要完全理解此代码的工作原理:

  1. 要查看检查任何元素是否为异常值的完整结果,请在其列中运行:

     df[cols_to_check].apply(isOutlier, thr=1.5)

    您将isOutlier函数应用于cols_to_check列表中的每一列,传递所选的阈值值。 结果是:

     price b_d100_p a_d052_p 101 False False False 102 False False False 102 False False False 104 False False False 105 True False True 106 False False True 107 True False False 107 False False False 107 False False False 107 False False False
  2. 要获取每一行的累积结果(无论一行中的任何元素为True ),请运行:

     df[cols_to_check].apply(isOutlier, thr=1.5).any(axis=1)

    结果是:

     101 False 102 False 102 False 104 False 105 True 106 True 107 True 107 False 107 False 107 False dtype: bool

因此,如果您运行df[~...]您将获得上述条件为False 的行,并且应将此结果保存回df

请注意,您要删除至少包含一个异常值的行,而不是将异常值更改为NaN (因为它是您的代码的结果)。

为了使您的方法提供所需的输出,您只需要将异常值去除应用于数据帧df的指定列

df[row_with_potential_outliers] = df[row_with_potential_outliers][abs((df[row_with_potential_outliers] - df[row_with_potential_outliers].mean()) / df[row_with_potential_outliers].std()) < 1.5]

    side    price  b_d100_v  b_d100_p  a_d052_v  a_d052_p
101    a  10400.0       1.0   10390.0      11.0   10399.0
102    a  10400.0       1.0   10391.0      11.0   10403.0
102    a  10400.0       1.0   10390.0      11.0   10400.0
104    b  10380.0       0.3   10390.0       9.3   10401.0
105    a      NaN      10.0   10390.5       0.1       NaN
106    a  10400.0      10.0   10385.0       0.1       NaN
107    a      NaN      10.0   10385.0       0.1   10400.0
107    b  10400.0      10.0   10386.0       0.1   10400.0
107    b  10399.0       9.0   10387.0       0.2   10402.0
107    a  10399.0       9.0   10387.0       0.3   10404.0

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM