我有一个场景,用户希望对一个数据帧或序列对象应用几个过滤器。本质上,我想有效地将用户在运行时指定的一系列过滤(比较操作)链接在一起
过滤器应为添加剂(即,应用的每个过滤器应缩小结果范围)
我目前正在使用reindex(),但每次都会创建一个新对象并复制底层数据(如果我正确理解文档的话)。因此,在过滤大型系列或数据帧时,这可能会非常低效
我认为使用apply()、map()或类似的方法可能会更好。我对熊猫还不太熟悉,所以我还是试着去了解一切
TL;博士
我希望采用以下形式的字典,将每个操作应用于给定的Series对象,并返回一个“筛选”的Series对象
relops={'>;=':[1],'<;=':[1]}
长例子
我将从一个我目前拥有的示例开始,只过滤一个序列对象。以下是我当前使用的函数:
def应用再操作(系列,再操作):
"""
传递关系运算符字典以在给定的系列对象上执行
"""
对于op,relops.iteritems()中的VAL:
op_func=ops[op]
对于val中的val:
过滤=运算函数(系列,val)
series=series.reindex(series[过滤])
返回序列
用户提供一个字典,其中包含要执行的操作:
>&燃气轮机&燃气轮机;数据帧({'col1':[0,1,2],'col2':[10,11,12]})
&燃气轮机&燃气轮机&燃气轮机;打印df
&燃气轮机&燃气轮机&燃气轮机;打印df
col1 col2
0 0 10
1 1 11
2 2 12
&燃气轮机&燃气轮机&燃气轮机;从ge的运营商进口
&燃气轮机&燃气轮机&燃气轮机;ops={'>;=':ge'<;=':le}
&燃气轮机&燃气轮机&燃气轮机;应用重新操作(df['col1'],{'>;=':[1]})
可乐
1 1
2 2
姓名:col1
&燃气轮机&燃气轮机&燃气轮机;应用_relops(df['col1',relops={'>;=':[1],'<;=':[1]})
可乐
1 1
姓名:col1
同样,我上述方法的“问题”是,我认为中间步骤可能存在大量不必要的数据复制
此外,我还想对此进行扩展,以便传入的字典可以包括要运算符打开的列,并基于输入字典过滤整个数据帧。然而,我假设任何适用于该系列的东西都可以轻松地扩展为数据帧
熊猫(和numpy)允许布尔索引,这将更加有效:
[11]on
:df.loc[df['col1']>;=1'col1']
Output[11]:
1 1
2 2
姓名:col1
At[12]on:df[df['col1']>;=1]
Output[12]:
col1 col2
1 1 11
2 2 12
At[13]on:df[(df['col1']>;=1)&;(df['col1']<;=1)]
Output[13]:
col1 col2
1 1 11
如果您想为此编写帮助函数,请考虑以下几行:
[14]on
:定义b(x,col,op,n):
返回op(x[col],n)
At[15]on:定义f(x,*b):
返回x[(np.logical_和(*b))]
In[16]:b1=b(df,'col1',ge,1)
In[17]:b2=b(df,'col1',le,1)
In[18]:f(df,b1,b2)
Output[18]:
col1 col2
1 1 11
更新:pandas 0.13为此类用例提供了一种查询方法,假设列名是有效的标识符,下面的工作(并且对于大帧来说可能更有效,因为它在幕后使用numexpr):
[21]on
:df.query('col1<;=1<;=col1')
Output[21]:
col1 col2
1 1 11