在DataFrame中的列子集上进行逻辑或

发布于 2021-01-29 19:29:24

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

我目前正在做:

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

其中mylist是与的列有关的字符串列表df。但我想在不限长度的情况下进行此操作mylist。

我能想到的唯一方法是循环mylist并为其每个元素创建一个新的数据框,然后进行合并/合并或其他操作。但这对我来说并不聪明。

有没有更好的办法?

关注者
0
被浏览
46
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    建立在LondonRob的答案上,您可以使用

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

    与每行一次调用Python的内置函数any相比apply,调用DataFrame的方法将具有更好的性能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)])
    

    产生其中至少一列为True的行:

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


知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看