Pandas 系列参数函数记忆

Pandas Series argument function memoization

我想记忆一个带有可变参数的函数(Pandas 系列对象)。有什么办法可以做到这一点?

这是一个简单的斐波那契示例,参数是一个 Pandas 系列,其中第一个元素代表序列的索引。

示例:

from functools import lru_cache

@lru_cache(maxsize=None)
def fib(n):
    if n.iloc[0] == 1 or n.iloc[0] == 2:
        return 1
    min1 = n.copy()
    min1.iloc[0] -=1
    min2 = n.copy()
    min2.iloc[0] -= 2 
    return fib(min1) + fib(min2)

调用函数:

fib(pd.Series([15,0]))

结果:

TypeError: 'Series' objects are mutable, thus they cannot be hashed

预期用途更复杂,所以我发布了这个无用但简单的示例。

多个选项:

  • 将可变对象转换为不可变对象,例如字符串或元组。
  • 创建可变对象的散列并将其用作备忘录字典键。哈希冲突的风险。
  • 创建一个实现 __hash__() 函数的不可变子类。

我写了一个包装器,按照@abarnert 和@Calvin 的建议用一个元组(冻结等效)替换 Pandas 系列参数。由于元组是不可变的,因此现在可以记忆该函数。

def freeze_series(f):
    def wrapper(series):
        return f(tuple(series.to_dict(OrderedDict).items()))
    return wrapper

这是一个将元组解冻回 Pandas 系列的普通函数:

def unfreeze_series(frozen_series):
    return pd.Series(OrderedDict((x, y) for x, y in frozen_series))

解题示例可以这样实现:

from functools import lru_cache

@freeze_series
@lru_cache(maxsize=None)
def fib(n):
    n = unfreeze_series(n)
    if n.iloc[0] == 1 or n.iloc[0] == 2:
        return 1
    min1 = n.copy()
    min1.iloc[0] -=1
    min2 = n.copy()
    min2.iloc[0] -= 2 
    return fib(min1) + fib(min2)