Pandas DataFrame:如何在多个条件下选择行?

时间:2017-08-09 12:30:06

标签: python pandas dictionary

我正在尝试根据需要全部满足的条件列表来选择DataFrame的行。 这些条件存储在字典中,格式为{column:max-value}。

这是一个例子:dict = {'name': 4.0, 'sex': 0.0, 'city': 2, 'age': 3.0}

我需要选择所有DataFrame行,其中相应的属性小于或等于字典中的相应值。

我知道根据两个或多个条件选择行我可以写:

rows = df[(df[column1] <= dict[column1]) & (df[column2] <= dict[column2])]

我的问题是,如何以Pythonic方式选择与字典中存在的条件匹配的行? 我试过这种方式,

keys = dict.keys() 
rows = df[(df[kk] <= dict[kk]) for kk in keys]

但它给了我一个错误=“[ expected”,即使放入[符号也不会消失。

3 个答案:

答案 0 :(得分:4)

我们可以使用DataFrame.query()这样的方法:

In [109]: dct = {'name': 4.0, 'sex': 0.0, 'city': 2, 'age': 3.0}

In [110]: qry = ' and '.join(['{} <= {}'.format(k,v) for k,v in dct.items()])

In [111]: qry
Out[111]: 'name <= 4.0 and sex <= 0.0 and city <= 2 and age <= 3.0'

In [112]: df.query(qry)
...

答案 1 :(得分:2)

您可以利用Pandas的自动轴对齐。给定具有列['age', 'city', 'name', 'sex']的DataFrame和具有相同索引的Series,您可以使用

将DataFrame中的每个条目与Series中的相应值进行比较。
In [29]: df < pd.Series(dct)
Out[29]: 
      age   city   name    sex
0   False  False  False  False
1   False  False  False  False
2    True  False  False  False
3   False   True  False  False
4    True   True   True  False
...

然后,您可以使用

找到所有True的行
mask = (df <= pd.Series(dct)).all(axis=1)

并选择df.loc[mask, :]的行。例如,

import numpy as np
import pandas as pd
np.random.seed(2017)
N = 300
df = pd.DataFrame({'name':np.random.randint(10, size=N),
                   'sex':np.random.randint(2, size=N),
                   'city':np.random.randint(10, size=N),
                   'age':np.random.randint(10, size=N)})
dct = {'name': 4.0, 'sex': 0.0, 'city': 2, 'age': 3.0}

mask = (df <= pd.Series(dct)).all(axis=1)
print(df.loc[mask, :])

产量

     age  city  name  sex
7      3     2     0    0
10     1     2     4    0
150    1     2     4    0
188    2     2     2    0
198    3     2     3    0
229    1     2     0    0
254    1     2     2    0
275    3     2     1    0
276    0     1     4    0
299    3     1     2    0

答案 2 :(得分:0)

您也可以尝试:

import pandas as pd
import numpy as np


N = 300

df = pd.DataFrame({'name':np.random.randint(10, size=N),
                   'sex':np.random.randint(2, size=N),
                   'city':np.random.randint(10, size=N),
                   'age':np.random.randint(10, size=N)})

dct = {'name': 4.0, 'sex': 0.0, 'city': 2, 'age': 3.0}

df.loc[np.prod([df[k] <= v for k,v in dct.items()],axis=0).astype(bool),:]

#      age  city  name  sex
# 7      3     2     0    0
# 10     1     2     4    0
# 150    1     2     4    0
# 188    2     2     2    0
# 198    3     2     3    0
# 229    1     2     0    0
# 254    1     2     2    0
# 275    3     2     1    0
# 276    0     1     4    0
# 299    3     1     2    0