Pandas系列(Series)参数函数记忆化

3
我希望能将带有可变参数(Pandas Series对象)的函数进行记忆化。是否有任何方法可以实现这一点?
以下是一个简单的斐波那契数列示例,其中参数是一个Pandas Series对象,第一个元素表示序列的索引。
示例:
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

由于使用目的较为复杂,因此我发布了这个毫无用处但简单明了的示例。


1
我们可以看一下你的代码吗? - cs95
1
你有什么问题?为什么无法对可变值进行哈希处理? - user1781434
1
如果您想通过某些可变字段的相等性进行备忘,但您知道在缓存的生命周期中它们不会被改变,那么您需要"冻结"这些字段,例如将列表复制到元组中,或者在类中创建一个不安全但有用的__hash__方法(或者是一个安全的方法,具有冻结实例的API,以便在冻结之前抛出故障)。 - abarnert
1
我猜你接下来的问题可能是如何高效简便地创建一个 Pandas series 的冻结等价物... 我不知道答案,但你可以去搜索一下,如果找不到答案的话,再提出一个具体的问题。 - abarnert
1
你可以通过使用一个冻结序列持有者来实现,该持有者在构建时手动计算哈希值,例如,哈希值为元组的元组的值,并在任何地方使用这些持有者,但可能存在更简单的方法。 - abarnert
显示剩余8条评论
2个回答

1

几个选项:

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

1

我编写了一个包装器,用一个元组(冻结等效)替换了Pandas系列参数,正如@abarnert和@Calvin建议的那样。由于元组是不可变的,所以现在可以对该函数进行记忆化处理。

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)

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