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

为什么在此函数中串联由DataFrame列的名称生成的字符串项列表失败?

  •  1
  • thagomizer  · 技术社区  · 1 年前

    在函数内部与外部执行列表串联时,我遇到了一个无法解释的问题。具体来说,我尝试在函数内部和函数外部连接DataFrame列名的列表。外表看起来很好,但内心却出现了错误。请参阅下面的示例。

    实例 :假设我想编写一个函数,返回一列的多个滞后,并根据原始列名为滞后变量指定新名称。我可以这样做:

    import pandas as pd
    import numpy as np
    rng = np.random.default_rng(22222222)
    
    df = pd.DataFrame({'X':rng.random(10)})
    
    print(df)
    
              X
    0  0.279384
    1  0.838032
    2  0.298536
    3  0.056188
    4  0.532023
    5  0.560038
    6  0.127512
    7  0.322774
    8  0.813949
    9  0.245242
    

    制作函数:

    def lagger(column, lags): #Takes as input a DataFrame column in the form df[colname]
        lags = [column.shift(i) for i in range(1, lags+1)]
    
        df = pd.concat(lags, axis=1) #a DataFrame with a column for each lag.
    
        names = [f"{column.name}_L{i}" for i in range(1,lags+1)] #generate new names
    
        df.rename(names, axis='columns', inplace=True)
    
        return df
    

    在测试函数时,我得到了以下错误:

    ---------------------------------------------------------------------------
    TypeError                                 Traceback (most recent call last)
    Cell In[27], line 1
    ----> 1 lagger(df['X'], 3)
    
    Cell In[25], line 6
          2 lags = [column.shift(i) for i in range(1, lags+1)]
          4 df = pd.concat(lags, axis=1) #a DataFrame with a column for each lag.
    ----> 6 names = [f"{column.name}_L{i}" for i in range(1,lags+1)] #generate new names
          8 df.rename(names, axis='columns', inplace=True)
         10 return df
    
    TypeError: can only concatenate list (not "int") to list
    

    列表理解出现了问题。让我们试着在函数之外进行类似的理解:

    [f"{df['X'].name}_L{i}" for i in range(1,4)]
    
    
    ['X_L1', 'X_L2', 'X_L3']
    

    工作得很好!

    这是怎么回事?为什么这在函数外部有效,而在函数内部无效?

    需要明确的是,我已经发现 this answer 这澄清了如何产生多个滞后。我不是在问这个。我在问做和做有什么区别 [f"{column.name}_L{i}" for i in range(1,lags+1)] 函数内部与 [f"{df['X'].name}_L{i}" for i in range(1,4)] 功能之外?为什么它在函数内部失败?

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

    您覆盖了您的参数 lags 在你的功能中有一个列表。因此 range(1, lags+1) 已经不起作用了。请使用其他名称。此外,您使用 rename 是不正确的,您应该使用 set_axis :

    def lagger(column, lags): #Takes as input a DataFrame column in the form df[colname]
        l = [column.shift(i) for i in range(1, lags+1)]
        df = pd.concat(l, axis=1) #a DataFrame with a column for each lag.
        names = [f"{column.name}_L{i}" for i in range(1, lags+1)] #generate new names
        return df.set_axis(names, axis='columns')
    
    lagger(df['X'], 3)