代码之家  ›  专栏  ›  技术社区  ›  William

熊猫公园。应用函数不能对python缓存进行哈希运算”

  •  0
  • William  · 技术社区  · 2 年前

    我有一个df,您可以通过运行以下代码来获得它:

    import pandas as pd
    from io import StringIO
    from functools import lru_cache
    
    df = """
      contract      EndDate     
      A00118        123456
      A00118        12345   
    """
    df = pd.read_csv(StringIO(df.strip()), sep='\s+')
    

    输出为:

        contract    EndDate
    0   A00118     123456
    1   A00118     12345
    

    然后我对每一行应用了一个逻辑:

    def var_func(row,n):
        res=row['EndDate']*100*n
        return res
    
    df['annfact'] = df.apply(lambda row: var_func(row,10), axis=1)
    

    输出为:

        contract    EndDate annfact
    0   A00118     123456   123456000
    1   A00118     12345    12345000
    

    但是,如果我在此函数上应用python lru\u缓存:

    @lru_cache(maxsize = None)
    def var_func(row,n):
        res=row['EndDate']*100*n
        return res
    
    df['annfact'] = df.apply(lambda row: var_func(row,10), axis=1)
    

    错误:

    TypeError: ("'Series' objects are mutable, thus they cannot be hashed", 'occurred at index 0')
    

    有朋友可以帮忙吗?我想将python lru\U缓存应用于pd。应用函数。由于某些原因,我只能使用pd。应用函数,但不矢量化numpy方法。

    1 回复  |  直到 2 年前
        1
  •  1
  •   user7864386 user7864386    2 年前

    从…起 the docs :

    由于字典用于缓存结果,因此函数的位置参数和关键字参数必须是可哈希的。

    具有 df.apply(..., axis=1) ,您正在传递一个不可散列的行(这是一个序列对象),因此您会得到错误。

    解决这个问题的一个方法是 var_func 在列上:

    @lru_cache(maxsize = None)
    def var_func(row, n):
        return row*100*n
    
    df['annfact'] = df['EndDate'].apply(var_func, n=10)
    

    对于您的特定示例,最好使用矢量化操作:

    df['annfact'] = df['EndDate']*100*n
    

    我们还可以将每一行转换为可散列的内容。由于您希望继续引用列名,我们可以使用 collections.namedtuple :

    @lru_cache(maxsize = None)
    def var_func(row, n):
        res=row.EndDate*100*n
        return res
    
    from collections import namedtuple
    df_as_ntup = namedtuple('df_as_ntup', df.columns)
    df['annfact'] = df.apply(lambda row: var_func(df_as_ntup(*row), 10), axis=1)
    

    输出:

      contract  EndDate    annfact
    0   A00118   123456  123456000
    1   A00118    12345   12345000