【问题标题】:Conditional filtering on dataframe with multiple columns对具有多列的数据框进行条件过滤
【发布时间】:2021-04-07 19:31:09
【问题描述】:

我有一个包含 80 列的数据框。其中,有大约 45 列我需要检查“全零”值过滤器。如果对于一行,所有这 45 列的值都为零,则该行被标记为 True。否则为 False。

以下是此问题的示例数据框:

df  = pd.DataFrame({'col1': [101,102,103,104,105,106,107,108,109,110,111],
                'col2': ['A','B','A','A','A','B','B','A','A','B','B'],
                'col3': [12e10,23e10,34e10,0,56e10,67e10,78e10,89e10,0,12e10,23e10],
                'col4': ['F','F','F','E','E','E','E','E','F','F','F'],
                'col5': [12e10,0,34e10,45e10,0,67e10,78e10,0,0,12e10,23e10],
                'col6': [12e10,0,34e10,0,0,67e10,78e10,0,0,12e10,23e10],
                'col7': [12e10,0,34e10,45e10,0,67e10,0,0,0,12e10,23e10],
                'col8': [12e10,0,34e10,45e10,0,67e10,78e10,0,0,12e10,23e10],
                'col9': [12e10,0,34e10,45e10,0,67e10,78e10,0,0,12e10,23e10],
                'col10': [12e10,0,0,45e10,0,67e10,78e10,0,0,12e10,23e10],
                'col11': [12e10,0,34e10,45e10,0,67e10,78e10,0,0,12e10,23e10],
                'col12': [12e10,0,34e10,0,0,67e10,78e10,0,0,12e10,23e10],
                'col13': [12e10,0,34e10,45e10,0,67e10,78e10,0,0,12e10,23e10],
                'col14': [12e10,0,34e10,45e10,0,67e10,0,0,0,12e10,23e10],
                'col15': [12e10,0,34e10,45e10,0,67e10,78e10,0,0,12e10,23e10],
                'col16': [12e10,0,34e10,45e10,0,67e10,78e10,0,0,12e10,0],
                'col17': [12e10,0,34e10,45e10,0,67e10,78e10,0,0,0,0],
                'col18': [12e10,0,34e10,45e10,0,67e10,78e10,0,0,12e10,23e10],
                'col19': [12e10,0,34e10,0,0,67e10,78e10,0,0,12e10,23e10],
                'col20': [12e10,0,0,45e10,0,67e10,78e10,0,0,12e10,23e10],
               })

现在,在此示例中,我需要检查从 col5 到 col19 的所有列的条件。 col3 和 col20 被排除在外。并且所有其他分类列也被排除在外。

我这样做是为了过滤掉那些行。

df[(df[col5] == 0) & (df[col6] == 0) & (df[col7] == 0) & ... & (df[col19] == 0)]

这将得到行(col1:102,105,108,109),因为它们的 col5 到 col19 都为零。 现在我需要为这些行在新列 df['mark'] 中放入 True,而在其余行中放入 False。

但我相信必须有一些简单的方法来做到这一点?

【问题讨论】:

    标签: python-3.x pandas dataframe filter


    【解决方案1】:

    您可以使用loc 索引,然后检查行的all 条目(axis=1)是否等于0(eq(0)):

    df["mark"] = df.loc[:, "col5": "col19"].eq(0).all(axis=1)
    

    得到

          col1 col2        col3 ...        col19         col20    mark
    0    101    A  1.200000e+11 ...  1.200000e+11  1.200000e+11  False
    1    102    B  2.300000e+11 ...  0.000000e+00  0.000000e+00   True
    2    103    A  3.400000e+11 ...  3.400000e+11  0.000000e+00  False
    3    104    A  0.000000e+00 ...  0.000000e+00  4.500000e+11  False
    4    105    A  5.600000e+11 ...  0.000000e+00  0.000000e+00   True
    5    106    B  6.700000e+11 ...  6.700000e+11  6.700000e+11  False
    6    107    B  7.800000e+11 ...  7.800000e+11  7.800000e+11  False
    7    108    A  8.900000e+11 ...  0.000000e+00  0.000000e+00   True
    8    109    A  0.000000e+00 ...  0.000000e+00  0.000000e+00   True
    9    110    B  1.200000e+11 ...  1.200000e+11  1.200000e+11  False
    10   111    B  2.300000e+11 ...  2.300000e+11  2.300000e+11  False
    

    如果列不连续,你可以事先写好它们的名字并在上面传递,例如:

    cols_to_look_for = ["col8", "col13", "col21", "col34"]
    df["mark"] = df.loc[:, cols_to_look_for].eq(0).all(axis=1)
    

    (在您在问题中给出的示例中,它们的连续性允许切片符号。)

    【讨论】:

    • 谢谢穆斯塔法。我不知道这个 eq() 方法。我尝试了 isin() 和所有这些,但都被卡住了。谢谢。
    • @sammywemmy 没有萨米。穆斯塔法做对了。我需要这个新列“标记”。
    • @sammywemmy 问题是“...现在我需要将 True 放入新列 df['mark']...”,实际上。
    • 是否有与 eq() 相对的等效“不相等”方法?
    【解决方案2】:

    我尝试了另一种方法,使用 sum() 和 map() 方法来获取必要的值。

    df['mark'] = np.sign(df.loc[:,'col5':'col19'].sum(axis=1)).map({-1:False,1:False,0:True})
    

    Mustafa 提交的解决方案在我的情况下是更快更好的方法。但是,如果您想要一个用于负值、正值和零值的特定指标而不是布尔值,这将有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-09-16
      • 1970-01-01
      • 2022-01-19
      • 2015-07-14
      • 1970-01-01
      • 2011-03-27
      相关资源
      最近更新 更多