我有一个场景,用户想要 将多个过滤器应用于 Pandas DataFrame 或 Series 对象。本质上,我想有效地将用户在运行时指定的一堆过滤(比较操作)链接在一起。
- 过滤器应该是可 加 的(也就是应用的每个过滤器都应该缩小结果)。
- 我目前正在使用
reindex()
(如下所示)但这每次都会创建一个新对象并复制基础数据(如果我正确理解文档)。我想避免这种不必要的复制,因为在过滤大型 Series 或 DataFrame 时效率非常低。 - 我认为使用
apply()
、map()
或类似的东西可能会更好。虽然我对 Pandas 还很陌生,但我仍然在努力思考所有事情。 - 另外,我想扩展它,以便 传入的字典可以包含要操作的列, 并根据输入字典过滤整个 DataFrame。但是,我假设任何适用于 Series 的东西都可以轻松扩展到 DataFrame。
长话短说
我想采用以下形式的字典并将每个操作应用于给定的 Series 对象并返回一个“过滤”的 Series 对象。
relops = {'>=': [1], '<=': [1]}
长例子
我将从我当前拥有的示例开始,并且只过滤单个 Series 对象。以下是我目前正在使用的功能:
def apply_relops(series, relops):
"""
Pass dictionary of relational operators to perform on given series object
"""
for op, vals in relops.iteritems():
op_func = ops[op]
for val in vals:
filtered = op_func(series, val)
series = series.reindex(series[filtered])
return series
用户提供一个字典,其中包含他们想要执行的操作:
>>> df = pandas.DataFrame({'col1': [0, 1, 2], 'col2': [10, 11, 12]})
>>> print df
>>> print df
col1 col2
0 0 10
1 1 11
2 2 12
>>> from operator import le, ge
>>> ops ={'>=': ge, '<=': le}
>>> apply_relops(df['col1'], {'>=': [1]})
col1
1 1
2 2
Name: col1
>>> apply_relops(df['col1'], relops = {'>=': [1], '<=': [1]})
col1
1 1
Name: col1
同样,我上述方法的“问题”是我认为中间步骤有很多可能不必要的数据复制。
原文由 durden2.0 发布,翻译遵循 CC BY-SA 4.0 许可协议
Pandas(和 numpy)允许使用 boolean indexing ,这会更有效率:
如果你想为此编写辅助函数,请考虑以下内容:
更新: pandas 0.13 有一个针对此类用例的查询方法,假设列名是以下工作的有效标识符(并且对于大帧可以更有效,因为它在幕后使用 numexpr ):