使用pandas:迭代过滤DataFrame的行

3
假设我有一个像这样的DataFrame
df = pd.DataFrame([['x', 1, 2], ['x', 1, 3], ['y', 2, 2]], 
                  columns=['a', 'b', 'c'])

为了选择所有c == 2且a == 'x'的行,我可以像这样操作:
df[(df['a'] == 'x') & (df['c'] == 2)]

或者我可以通过创建临时变量进行迭代的细化。

df1 = df[df['a'] == 'x']
df2 = df1[df1['c'] == 2]

有没有一种方法可以对行进行迭代优化?
(
  df
  .refine(lambda row: row['a'] == 'x')     # this method doesn't exist
  .refine(lambda row: row['c'] == 2)
)
2个回答

1

虽然现在还没有解决方案,但是在pandas版本0.13中,您将能够执行以下操作

df.query('a == "x"').query('c == 2')

我希望你能实现自己想要的目标。

你还可以做到以下事情:

df['a == "x"']['c == 2']

"and"。
df['a == "x" and c == 2']

标签未闭合

df[(df.a == 'x') & (df.c == 2)]

直到0.13版本为止?

1
这只是一种风格上的偏好。方法链使我的代码更清晰。Pandas 0.13会允许我使用任意行函数进行过滤,而不仅仅是通过DataFrame.query语法在单个列上进行简单比较吗? - duckworthd
@AndyHayden,听起来你在谈论惰性求值,这是一个比eval/query更广泛的话题。我正在研究filter方法,并想知道是否有类似于DataFrame内容(而不是轴)的东西可能会有用。我不反对使用refine... - Phillip Cloud
@PhillipCloud,就是我昨晚无法表达的那个词组。这是一个非常宽泛的话题,不确定我是否理解“内容”与“轴”的区别。 - Andy Hayden
@AndyHayden 我的意思是 DataFrame.filter 过滤轴信息(例如,匹配正则表达式的列),而 DataFrame.refine 方法将基于 DataFrame 中的值进行过滤。类似于 DataFrame.renameDataFrame.replace 之间的区别。 - Phillip Cloud
属性访问是一种摊销的常数时间操作(它是一个dict查找),除非您使用比此更慢的东西重载__getattribute____getattr__。在DataFrame(和pandas >= 0.12中的Series)的情况下,属性访问被重载为使用索引进行查找(其由khash哈希表支持),我认为这也提供了摊销的常数时间查找。因此,在这种情况下,没有属性访问的性能惩罚,只是看起来不太美观:( - Phillip Cloud
显示剩余3条评论

0
如果您有许多术语,其数量在运行时是未知的,您可以按如下方式操作。我并不是说这是实现目标的最佳方式,但在Pandas 0.14.1中我看不到其他选择:
df = pd.DataFrame([['x', 1, 2], ['x', 1, 3], ['y', 2, 2]],
                  columns=['a', 'b', 'c'])

conditions = {'a': 'x', 'c': 2}

def esc(term):
    if isinstance(term, str):
        return '"%s"' % term
    return str(term)

q_parts = ["%s == %s" % (k, esc(v)) for k, v in conditions.items()]
q = ' and '.join(q_parts)

print df.query(q)

当然,esc函数或更广泛的代码片段需要进一步扩展以处理逻辑非、x是否在(x, y, z)中等情况...

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