我在Pandas工作,我想在多个字段的数据框中应用多个过滤器。
我正在使用另一个更复杂的数据框架,但我正在简化这个问题的上下文。以下是示例数据框的设置:
dates = pd.date_range('20170101', periods=16)
rand_df = pd.DataFrame(np.random.randn(16,4), index=dates, columns=list('ABCD'))
将一个过滤器应用于此数据框已有详细记录且简单:
rand_df.loc[lambda df: df['A'] < 0]
因为lambda看起来像一个简单的布尔表达式。这样做很有诱惑力。这不起作用,因为它不是一个布尔表达式,而是一个可调用的。其中多个不能组合为布尔表达式:
rand_df.loc[lambda df: df['A'] < 0 and df[‘B’] < 0]
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-31-dfa05ab293f9> in <module>()
----> 1 rand_df.loc[lambda df: df['A'] < 0 and df['B'] < 0]
我找到了两种成功实现此方法的方法。我会将它们添加到潜在的答案中,因此您可以直接评论它们作为解决方案。但是,我想征求其他方法,因为我不确定其中任何一种方法都是过滤Pandas数据帧的非常标准的方法。
答案 0 :(得分:7)
In [3]: rand_df.query("A < 0 and B < 0")
Out[3]:
A B C D
2017-01-02 -0.701682 -1.224531 -0.273323 -1.091705
2017-01-05 -1.262971 -0.531959 -0.997451 -0.070095
2017-01-06 -0.065729 -1.427199 1.202082 0.136657
2017-01-08 -1.445050 -0.367112 -2.617743 0.496396
2017-01-12 -1.273692 -0.456254 -0.668510 -0.125507
或:
In [6]: rand_df[rand_df[['A','B']].lt(0).all(1)]
Out[6]:
A B C D
2017-01-02 -0.701682 -1.224531 -0.273323 -1.091705
2017-01-05 -1.262971 -0.531959 -0.997451 -0.070095
2017-01-06 -0.065729 -1.427199 1.202082 0.136657
2017-01-08 -1.445050 -0.367112 -2.617743 0.496396
2017-01-12 -1.273692 -0.456254 -0.668510 -0.125507
PS你会在the Pandas docs
中找到很多例子答案 1 :(得分:4)
要使用lambda
,请不要传递整个列。
rand_df.loc[lambda x: (x.A < 0) & (x.B < 0)]
# Or
# rand_df[lambda x: (x.A < 0) & (x.B < 0)]
A B C D
2017-01-12 -0.460918 -1.001184 -0.796981 0.328535
2017-01-14 -0.146846 -1.088095 -1.055271 -0.778120
您可以使用布尔numpy数组加速评估
c1 = rand_df.A.values > 0
c2 = rand_df.B.values > 0
rand_df[c1 & c2]
A B C D
2017-01-12 -0.460918 -1.001184 -0.796981 0.328535
2017-01-14 -0.146846 -1.088095 -1.055271 -0.778120
答案 2 :(得分:3)
rand_df[(rand_df.A < 0) & (rand_df.B <0)]
答案 3 :(得分:2)
这是一种“链”使用'loc'操作的方法:
rand_df.loc[lambda df: df['A'] < 0].loc[lambda df: df['B'] < 0]
答案 4 :(得分:1)
这是一种方法,包括编写一个方法来进行过滤。我确信某些过滤器足够复杂或复杂,方法是最好的方法(这种情况并不复杂。)另外,当我使用Pandas并且我写了一个“for”循环时,我觉得我我做错了。
def lt_zero_ab(df):
result = []
for index, row in df.iterrows():
if row['A'] <0 and row['B'] <0:
result.append(index)
return result
rand_df.loc[lt_zero_ab]