DataFrame中列的子集上的逻辑OR

时间:2015-07-24 08:52:33

标签: python pandas

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

我现在正在做:

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

其中mylist是与df列相关的字符串列表。但我想在mylist

的任何长度内执行此操作

我能想到的唯一方法就是循环mylist并为其中的每个元素创建一个新的数据帧,然后合并/连接或其他任何内容。但这对我来说并不是很聪明。

有更好的方法吗?

2 个答案:

答案 0 :(得分:3)

根据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 (因为NaNs是浮动值)。所以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

答案 1 :(得分:3)

使用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

您可以使用any df axis=1行中的apply功能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

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

BaseException