Python 使用pandas.DataFrame中的复杂条件进行选择

Python 使用pandas.DataFrame中的复杂条件进行选择,python,pandas,Python,Pandas,例如,我有简单的DF: import pandas as pd from random import randint df = pd.DataFrame({'A': [randint(1, 9) for x in xrange(10)], 'B': [randint(1, 9)*10 for x in xrange(10)], 'C': [randint(1, 9)*100 for x in xrange(10)]})

例如,我有简单的DF:

import pandas as pd
from random import randint

df = pd.DataFrame({'A': [randint(1, 9) for x in xrange(10)],
                   'B': [randint(1, 9)*10 for x in xrange(10)],
                   'C': [randint(1, 9)*100 for x in xrange(10)]})
我可以使用Pandas的方法和习惯用法从“A”中选择相应的值,其中“B”的对应值大于50,而“C”的对应值不等于900吗?

当然!设置:

>>> import pandas as pd
>>> from random import randint
>>> df = pd.DataFrame({'A': [randint(1, 9) for x in range(10)],
                   'B': [randint(1, 9)*10 for x in range(10)],
                   'C': [randint(1, 9)*100 for x in range(10)]})
>>> df
   A   B    C
0  9  40  300
1  9  70  700
2  5  70  900
3  8  80  900
4  7  50  200
5  9  30  900
6  2  80  700
7  2  80  400
8  5  80  300
9  7  70  800
我们可以应用列操作并获取布尔系列对象:

>>> df["B"] > 50
0    False
1     True
2     True
3     True
4    False
5    False
6     True
7     True
8     True
9     True
Name: B
>>> (df["B"] > 50) & (df["C"] == 900)
0    False
1    False
2     True
3     True
4    False
5    False
6    False
7    False
8    False
9    False
[更新,切换到新样式
.loc
]:

然后我们可以用这些索引到对象中。对于读取访问,您可以链接索引:

>>> df["A"][(df["B"] > 50) & (df["C"] == 900)]
2    5
3    8
Name: A, dtype: int64
但是,由于视图和副本之间的差异,您可能会遇到麻烦,因为这样做是为了进行写访问。您可以改用
.loc

>>> df.loc[(df["B"] > 50) & (df["C"] == 900), "A"]
2    5
3    8
Name: A, dtype: int64
>>> df.loc[(df["B"] > 50) & (df["C"] == 900), "A"].values
array([5, 8], dtype=int64)
>>> df.loc[(df["B"] > 50) & (df["C"] == 900), "A"] *= 1000
>>> df
      A   B    C
0     9  40  300
1     9  70  700
2  5000  70  900
3  8000  80  900
4     7  50  200
5     9  30  900
6     2  80  700
7     2  80  400
8     5  80  300
9     7  70  800

请注意,我无意中键入了
==900
,而不是
!=900
,或
~(df[“C”]==900)
,但我太懒了,无法修复它。读者练习:^)

另一个解决方案是使用以下方法:

现在,如果要更改A列中的返回值,可以保存它们的索引:

my_query_index = df.query('B > 50 & C != 900').index
..并使用
.iloc
对其进行更改,即:

df.iloc[my_query_index, 0] = 5000

print df

      A   B    C
0     7  20  300
1  5000  80  700
2  5000  90  100
3     4  30  900
4  5000  80  200
5  5000  60  800
6     3  80  900
7     9  40  100
8     6  40  100
9     3  10  600

您可以使用pandas,因为它有一些内置函数用于比较。因此,如果您想要选择满足“B”和“C”条件的“A”值(假设您想要返回数据帧对象)

df['A'][df.B.gt(50)和df.C.ne(900)]

df[['A']]
将以数据帧格式返回列A


“gt”函数将返回B列大于50的位置,“ne”将返回不等于900的位置。

记住使用括号

请记住,
&
运算符优先于
10和df['B']<15]
这将导致

TypeError:无法将dtyped[float64]数组与[bool]类型的标量进行比较


关于
.loc
更新-如果您澄清我们从何处获取副本以及从何处获取视图,这将是一件好事。是否可以过滤pandas数据帧并使用OR运算符。例如,如果有一列month,您是否可以说df=data['month'==JAN或'month'==FEB]?可能还包括第二列,使查询更加复杂,newdf,其中col_month=jan或feb,col_day=MONDAY或WENDNESDAY@yoshiserry:请作为单独的问题提问。没有人会在对旧答案的评论中看到它。别忘了括号-你会得到一些奇怪的错误,比如
{TypeError}无法将数据类型的[int64]数组与[bool]类型的标量进行比较。
使用括号不是会导致整个系列的计算吗?如果我们想重复子集以提高效率,该怎么办?
df.query
pd.eval
似乎非常适合这个用例。有关
pd.eval()
函数系列及其特性和用例的信息,请访问。不妨查看@Gecko的答案:将每个条件都用括号括起来非常重要!我有一个嵌套的条件,其中一个条件没有被包装,导致了一段时间的错误,直到我看到这篇文章。谢谢
df.iloc[my_query_index, 0] = 5000

print df

      A   B    C
0     7  20  300
1  5000  80  700
2  5000  90  100
3     4  30  900
4  5000  80  200
5  5000  60  800
6     3  80  900
7     9  40  100
8     6  40  100
9     3  10  600
4 < 5 & 6 > 4
df.loc[(df['A'] > 10) & (df['B'] < 15)]
df.loc[df['A'] > 10 & df['B'] < 15]