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)
我想记忆一个带有可变参数的函数(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)