使用多个布尔列过滤pandas数据框

41

我希望你能够帮助我筛选一个含有多个布尔型变量的数据框,但是我一直无法达成目标。

样本数据:

A | B | C | D
John Doe | 45 | True | False
Jane Smith | 32 | False | False
Alan Holmes | 55 | False | True
Eric Lamar | 29 | True | True

列 C 和 D 的数据类型是布尔型。我想创建一个只包含 C 或 D 为真的行的新数据框 df1。它应该长这样:

A | B | C | D
John Doe | 45 | True | False
Alan Holmes | 55 | False | True
Eric Lamar | 29 | True | True

我尝试过类似这样的东西,但由于无法处理布尔类型而出现了问题:

df1 = df[(df['C']=='True') or (df['D']=='True')]

有什么想法吗?


4
布尔类型应该不加引号地引用,除非它被存储为字符串。 - salient
5个回答

76
In [82]: d
Out[82]:
             A   B      C      D
0     John Doe  45   True  False
1   Jane Smith  32  False  False
2  Alan Holmes  55  False   True
3   Eric Lamar  29   True   True

解决方案 1:

In [83]: d.loc[d.C | d.D]
Out[83]:
             A   B      C      D
0     John Doe  45   True  False
2  Alan Holmes  55  False   True
3   Eric Lamar  29   True   True

解决方案2:

In [94]: d[d[['C','D']].any(1)]
Out[94]:
             A   B      C      D
0     John Doe  45   True  False
2  Alan Holmes  55  False   True
3   Eric Lamar  29   True   True

解决方案 3:

In [95]: d.query("C or D")
Out[95]:
             A   B      C      D
0     John Doe  45   True  False
2  Alan Holmes  55  False   True
3   Eric Lamar  29   True   True

提示:如果你将解决方案更改为:

df[(df['C']==True) | (df['D']==True)]

它也能工作

Pandas文档 - 布尔索引


为什么我们不应该使用“PEP complaint”df[“col_name”] is True而应该使用df[“col_name”] == True

In [11]: df = pd.DataFrame({"col":[True, True, True]})

In [12]: df
Out[12]:
    col
0  True
1  True
2  True

In [13]: df["col"] is True
Out[13]: False               # <----- oops, that's not exactly what we wanted

兄弟,我觉得大多数问答者都被我们宠坏了... :) 很好的解决方案。 - BENY
哇,你已经掌握了所有的基础知识。我很难想出答案 :p - cs95
3
df[(df.var == True)].count() 对我来说会触发 E712(使用 is True 而不是 ==) - kev
1
@kev,谢谢你的建议,但是(df['C'] is True)将始终返回False,与数据无关。我认为这不会改善我的答案 ;) - MaxU - stand with Ukraine
1
@kev,我不会故意破坏代码(df ["col_name"] is True - 会产生错误结果),只为了符合PEP规范。我在答案中添加了一个示例。顺便说一下,我的答案中有三个选项,它们都符合PEP规范 ;) - MaxU - stand with Ukraine
显示剩余4条评论

15

太好了!更多选项!

np.where

df[np.where(df.C | df.D, True, False)]

             A   B      C      D
0     John Doe  45   True  False
2  Alan Holmes  55  False   True
3   Eric Lamar  29   True   True  

pd.Series.wheredf.index 上的应用


df.loc[df.index.where(df.C | df.D).dropna()]

               A   B      C      D
0.0     John Doe  45   True  False
2.0  Alan Holmes  55  False   True
3.0   Eric Lamar  29   True   True

df.select_dtypes

df[df.select_dtypes([bool]).any(1)]   

             A   B      C      D
0     John Doe  45   True  False
2  Alan Holmes  55  False   True
3   Eric Lamar  29   True   True
滥用 np.select
df.iloc[np.select([df.C | df.D], [df.index])].drop_duplicates()

             A   B      C      D
0     John Doe  45   True  False
2  Alan Holmes  55  False   True
3   Eric Lamar  29   True   True

@Wen 大多数这些解决方案都不太好,但我在寻找它们的过程中很开心。我认为 np.where 是最好的一个。 - cs95
1
太酷了!我从来没有想到过使用“np.select”+1 :) - MaxU - stand with Ukraine

5
或者
d[d.eval('C or D')]

Out[1065]:
             A   B      C      D
0     John Doe  45   True  False
2  Alan Holmes  55  False   True
3   Eric Lamar  29   True   True

评估(Eval),这是我的第一选择!(在此之后不得不寻找另一个选项) - cs95

1
所以,最简单的方法是:
students = [ ('jack1', 'Apples1' , 341) ,
             ('Riti1', 'Mangos1'  , 311) ,
             ('Aadi1', 'Grapes1' , 301) ,
             ('Sonia1', 'Apples1', 321) ,
             ('Lucy1', 'Mangos1'  , 331) ,
             ('Mike1', 'Apples1' , 351),
              ('Mik', 'Apples1' , np.nan)
              ]
#Create a DataFrame object
df = pd.DataFrame(students, columns = ['Name1' , 'Product1', 'Sale1']) 
print(df)


    Name1 Product1  Sale1
0   jack1  Apples1    341
1   Riti1  Mangos1    311
2   Aadi1  Grapes1    301
3  Sonia1  Apples1    321
4   Lucy1  Mangos1    331
5   Mike1  Apples1    351
6     Mik  Apples1    NaN

# Select rows in above DataFrame for which ‘Product’ column contains the value ‘Apples’,
subset = df[df['Product1'] == 'Apples1']
print(subset)

 Name1 Product1  Sale1
0   jack1  Apples1    341
3  Sonia1  Apples1    321
5   Mike1  Apples1    351
6     Mik  Apples1    NA

# Select rows in above DataFrame for which ‘Product’ column contains the value ‘Apples’, AND notnull value in Sale

subsetx= df[(df['Product1'] == "Apples1")  & (df['Sale1'].notnull())]
print(subsetx)
    Name1   Product1    Sale1
0   jack1   Apples1      341
3   Sonia1  Apples1      321
5   Mike1   Apples1      351

# Select rows in above DataFrame for which ‘Product’ column contains the value ‘Apples’, AND Sale = 351

subsetx= df[(df['Product1'] == "Apples1")  & (df['Sale1'] == 351)]
print(subsetx)

   Name1 Product1  Sale1
5  Mike1  Apples1    351

# Another example
subsetData = df[df['Product1'].isin(['Mangos1', 'Grapes1']) ]
print(subsetData)

Name1 Product1  Sale1
1  Riti1  Mangos1    311
2  Aadi1  Grapes1    301
4  Lucy1  Mangos1    331

这是代码的来源: https://thispointer.com/python-pandas-select-rows-in-dataframe-by-conditions-on-multiple-columns/
我对其进行了微小的更改。


-2

你可以轻松尝试这个:

df1 = df[(df['C']=='True') | (df['D']=='True')]

注意:
  1. 需要用按位或运算符 | 替换逻辑运算符 or
  2. 确保使用 () 将每个操作数括起来。

2
这与半年前已经给出的答案相似,但并不起作用。请下次在示例数据上尝试一下。 - Nico Albers

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接