Python 和 Pandas 中的函数式编程

Functional programming in Python with Pandas

我很想知道如何在函数式编程范例中重写以下函数 foo。我无法弄清楚如何将 filter_df() 应用于 kwargs 中的列并存储输出而不更改原始 DataFrame 对象 df.

的值

def foo(df, **kwargs):
    for column, values in kwargs.items():
        df = filter_df(df, column, values)
    return df

def filter_df(df, column, values):
    return df.loc[df[column].isin(values)].reset_index(drop=True)

对我来说一个明显的解决方案可能是将新变量 df_new 分配给 filter_df 的输出,例如

def foo(df, **kwargs):
    for column, values in kwargs.items():
        df_new = filter_df(df, column, values)
    return df_new

但是,这并不是特别有效的内存,因为 df 可能非常大。另外,我不确定这个选项是否会被归类为纯功能选项,因为 df_new 会影响每个循环迭代。

不是很清楚你的意思

re-write the following function, foo, within the functional programming paradigm.

并由

However, this is not particularly memory efficient as df could be quite large. Also, I'm not sure if this option be would classed as purely functional because df_new is affected on each loop iteration.

请注意,您对 foo 的第二个定义不会产生与第一种情况相同的输出,它只会 returns 符合最后一个条件的行并忽略其余条件。

在每次迭代中,filter_df 生成一个新对象(满足 df[column].isin(values) 的 DataFrame 行),因为 reset_index 不执行 in-place。 df_new 不受“每次循环迭代的影响”,名称 df_new 只是 re-binded (即指向)每次迭代中的新对象。单独应用条件,仅返回最后一个产生的 DataFrame。

解决方案

在这种特殊情况下,foo 可以使用 DataFrame.query 进行简化。这样你就不会创建不必要的中间数据帧。

def foo(df, **kwargs):
    query = ' and '.join(f'{col} in {vals}' for col, vals in kwargs.items())
    return df.query(query)