pandas中的大多数操作都可以通过操作符链接(groupby、聚合、应用等)来完成,但我发现过滤行的唯一方法是通过普通的括号索引
df_filtered = df[df['column'] == value]
这是没有吸引力的,因为它要求我分配df到一个变量,然后才能过滤它的值。还有像下面这样的吗?
df_filtered = df.mask(lambda x: x['column'] == value)
pandas中的大多数操作都可以通过操作符链接(groupby、聚合、应用等)来完成,但我发现过滤行的唯一方法是通过普通的括号索引
df_filtered = df[df['column'] == value]
这是没有吸引力的,因为它要求我分配df到一个变量,然后才能过滤它的值。还有像下面这样的吗?
df_filtered = df.mask(lambda x: x['column'] == value)
当前回答
pandas为Wouter Overmeire的答案提供了两种不需要重写的选择。一个是.loc[。,如在
df_filtered = df.loc[lambda x: x['column'] == value]
另一个是.pipe()
df_filtered = df.pipe(lambda x: x.loc[x['column'] == value])
其他回答
如果将列设置为作为索引进行搜索,则可以使用DataFrame.xs()获取横截面。这没有查询答案那么通用,但在某些情况下可能很有用。
import pandas as pd
import numpy as np
np.random.seed([3,1415])
df = pd.DataFrame(
np.random.randint(3, size=(10, 5)),
columns=list('ABCDE')
)
df
# Out[55]:
# A B C D E
# 0 0 2 2 2 2
# 1 1 1 2 0 2
# 2 0 2 0 0 2
# 3 0 2 2 0 1
# 4 0 1 1 2 0
# 5 0 0 0 1 2
# 6 1 0 1 1 1
# 7 0 0 2 0 2
# 8 2 2 2 2 2
# 9 1 2 0 2 1
df.set_index(['A', 'D']).xs([0, 2]).reset_index()
# Out[57]:
# A D B C E
# 0 0 2 2 2 2
# 1 0 2 1 1 0
我的答案和其他人的相似。如果您不想创建一个新函数,您可以使用pandas已经为您定义的函数。使用管道法。
df.pipe(lambda d: d[d['column'] == value])
只是想添加一个演示,使用loc不仅按行过滤,还按列过滤,以及链式操作的一些优点。
下面的代码可以按值筛选行。
df_filtered = df.loc[df['column'] == value]
通过稍微修改它,您还可以过滤列。
df_filtered = df.loc[df['column'] == value, ['year', 'column']]
为什么我们需要链式方法呢?答案是,如果您有很多操作,那么读取它就很简单。例如,
res = df\
.loc[df['station']=='USA', ['TEMP', 'RF']]\
.groupby('year')\
.agg(np.nanmean)
我不完全确定你想要什么,你的最后一行代码也没有帮助,但无论如何:
“链式”过滤是通过将布尔索引中的条件“链式”进行的。
In [96]: df
Out[96]:
A B C D
a 1 4 9 1
b 4 5 0 2
c 5 5 1 0
d 1 3 9 6
In [99]: df[(df.A == 1) & (df.D == 6)]
Out[99]:
A B C D
d 1 3 9 6
如果你想要链接方法,你可以添加你自己的掩码方法并使用它。
In [90]: def mask(df, key, value):
....: return df[df[key] == value]
....:
In [92]: pandas.DataFrame.mask = mask
In [93]: df = pandas.DataFrame(np.random.randint(0, 10, (4,4)), index=list('abcd'), columns=list('ABCD'))
In [95]: df.ix['d','A'] = df.ix['a', 'A']
In [96]: df
Out[96]:
A B C D
a 1 4 9 1
b 4 5 0 2
c 5 5 1 0
d 1 3 9 6
In [97]: df.mask('A', 1)
Out[97]:
A B C D
a 1 4 9 1
d 1 3 9 6
In [98]: df.mask('A', 1).mask('D', 6)
Out[98]:
A B C D
d 1 3 9 6
这个解决方案在实现方面比较粗糙,但我发现它在使用方面更简洁,而且肯定比其他提出的解决方案更通用。
https://github.com/toobaz/generic_utils/blob/master/generic_utils/pandas/where.py
你不需要下载整个回购:保存文件和做
from where import where as W
应该足够了。然后你可以这样使用它:
df = pd.DataFrame([[1, 2, True],
[3, 4, False],
[5, 7, True]],
index=range(3), columns=['a', 'b', 'c'])
# On specific column:
print(df.loc[W['a'] > 2])
print(df.loc[-W['a'] == W['b']])
print(df.loc[~W['c']])
# On entire - or subset of a - DataFrame:
print(df.loc[W.sum(axis=1) > 3])
print(df.loc[W[['a', 'b']].diff(axis=1)['b'] > 1])
一个稍微不那么愚蠢的用法示例:
data = pd.read_csv('ugly_db.csv').loc[~(W == '$null$').any(axis=1)]
顺便说一下,即使在使用布尔cols的情况下,
df.loc[W['cond1']].loc[W['cond2']]
能比吗
df.loc[W['cond1'] & W['cond2']]
因为它只在cond1为True时计算cond2。
免责声明:我第一次给出这个答案是因为我没有看到这个。