【问题标题】:Logical OR on a subset of columns in a DataFrame对 DataFrame 中的列子集进行逻辑或
【发布时间】:2015-07-24 08:52:32
【问题描述】:

我想获取(至少)df[mylist] 中的一列包含 True 的所有行。

我目前正在做:

df = df[ df[mylist[0]] | df[mylist[1]] | df[mylist[2]] ]

其中mylist 是与df 的列相关的字符串列表。但我想对mylist 的任意长度执行此操作。

我能想到的唯一方法是循环 mylist 并为它的每个元素创建一个新的数据框,然后合并/合并或任何它们。但这对我来说看起来不太聪明。

有没有更好的办法?

【问题讨论】:

  • 抱歉,您是说mylist 是一串列名称,例如['col1', 'col2', col3']?如果是这样,你为什么不直接做df[myList]?

标签: python pandas


【解决方案1】:

基于 LondonRob 的回答,您可以使用

df.loc[df[mylist].any(axis=1)]

调用 DataFrame 的 any 方法将比使用 apply 每行调用一次 Python 的内置 any 函数执行得更好。

或者你可以使用np.logical_or.reduce:

df.loc[np.logical_or.reduce(df[mylist], axis=1)]

对于大型 DataFrame,使用np.logical_or 可能更快:

In [30]: df = pd.DataFrame(np.random.binomial(1, 0.1, size=(100,300)).astype(bool))

In [31]: %timeit df.loc[np.logical_or.reduce(df, axis=1)]
1000 loops, best of 3: 261 µs per loop

In [32]: %timeit df.loc[df.any(axis=1)]
1000 loops, best of 3: 636 µs per loop

In [33]: %timeit df[df.apply(any, axis=1)]
100 loops, best of 3: 2.13 ms per loop

请注意,df.any 具有额外的功能,例如跳过 NaN 的能力。 在这种情况下,如果列是布尔值,则不能有任何 NaN (因为 NaN 是浮点值)。所以np.logical_or.reduce 更快。


import numpy as np
import pandas as pd
np.random.seed(2014)
df = pd.DataFrame(np.random.binomial(1, 0.1, size=(10,3)).astype(bool), 
                  columns=list('ABC'))
print(df)
#        A      B      C
# 0  False  False  False
# 1   True  False  False
# 2  False  False  False
# 3   True  False  False
# 4  False  False  False
# 5  False  False  False
# 6  False   True  False
# 7  False  False  False
# 8  False  False  False
# 9  False  False  False

mylist = list('ABC')
print(df[ df[mylist[0]] | df[mylist[1]] | df[mylist[2]] ])
print(df.loc[df[mylist].any(axis=1)])
print(df.loc[np.logical_or.reduce(df[mylist], axis=1)])

产生至少一列为真的行:

       A      B      C
1   True  False  False
3   True  False  False
6  False   True  False

【讨论】:

    【解决方案2】:

    使用python内置的any函数有一个非常更简单的方法:

    In []: mylist
    Out[]: ['A', 'B']
    
    In []: df
    Out[]: 
           A      B      C
    0  False  False  False
    1   True  False  False
    2  False  False  False
    3   True  False  False
    4  False  False  False
    5  False  False  False
    6  False   True  False
    7  False  False  False
    8  False  False  False
    9  False  False  False
    

    您可以使用axis=1 沿着df 的行apply 函数any。在这种情况下,我只会将 any 应用于列的子集:

    In []: df[mylist].apply(any, axis=1)
    Out[]: 
    0    False
    1     True
    2    False
    3     True
    4    False
    5    False
    6     True
    7    False
    8    False
    9    False
    dtype: bool
    

    这为我们提供了选择行的完美方式:

    In []: df[df[mylist].apply(any, axis=1)]
    Out[]: 
           A      B      C
    1   True  False  False
    3   True  False  False
    6  False   True  False
    

    【讨论】:

    • 在重新阅读现在更清晰的问题后,我意识到我的答案与 OP 想要的无关,尽管 OP 以一种高度混淆的方式表达了他们的问题
    猜你喜欢
    • 2021-06-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-09
    • 1970-01-01
    • 1970-01-01
    • 2016-03-20
    • 1970-01-01
    相关资源
    最近更新 更多