【问题标题】:Apply function to pandas dataframe row using values in other rows使用其他行中的值将函数应用于熊猫数据框行
【发布时间】:2016-09-06 01:42:14
【问题描述】:

我有一种情况,我有一个数据框行来执行计算,我需要使用后面(可能在前面)行中的值来进行这些计算(基本上是基于真实数据集的完美预测)。我从较早的 df.apply 调用中获取每一行,因此我可以将整个 df 传递给下游对象,但根据我分析中对象的复杂性,这似乎不太理想。

我找到了一个密切相关的问题和答案 [1],但问题实际上根本不同,因为我不需要整个 df 来进行计算,只需以下 x 行数(这可能很重要对于大 dfs)。

所以,例如:

df = pd.DataFrame([100, 200, 300, 400, 500, 600, 700, 800, 900, 1000], 
                  columns=['PRICE'])
horizon = 3

我需要在我的逐行 df.apply 调用中访问以下 3 (horizon) 行中的值。如何在我的逐行应用计算中动态地获得下一个 3 个数据点的天真预测?例如对于第一行,PRICE100,我需要在我的计算中使用[200, 300, 400] 作为预测。

[1]apply a function to a pandas Dataframe whose returned value is based on other rows

【问题讨论】:

    标签: python pandas lambda dataframe


    【解决方案1】:

    通过使用row.namedf.apply() 调用中获取行的索引,您可以生成与当前所在行相关的“预测”数据。这实际上是将“预测”放到相关行上的预处理步骤,或者如果 df 下游可用,它可以作为初始 df.apply() 调用的一部分来完成。

    df = pd.DataFrame(
        [100, 200, 300, 400, 500, 600, 700, 800, 900, 1000],
        columns=["PRICE"]
    )
    horizon = 3
        
    df["FORECAST"] = df.apply(
        lambda x: [df["PRICE"][x.name + 1 : x.name + horizon + 1]],
        axis=1
    )
    

    结果如下:

       PRICE          FORECAST
    0    100   [200, 300, 400]
    1    200   [300, 400, 500]
    2    300   [400, 500, 600]
    3    400   [500, 600, 700]
    4    500   [600, 700, 800]
    5    600   [700, 800, 900]
    6    700  [800, 900, 1000]
    7    800       [900, 1000]
    8    900            [1000]
    9   1000                []
    

    可以在您的行式df.apply() 计算中使用。

    编辑: 如果您想从生成的“预测”中删除索引:

    df["FORECAST"] = df.apply(
        lambda x: [df["PRICE"][x.name + 1 : x.name + horizon + 1].reset_index(drop=True)],
        axis=1
    )
    

    【讨论】:

      【解决方案2】:

      您可能会发现这也很有用。

      keys = range(horizon + 1)
      pd.concat([df.shift(-i) for i in keys], axis=1, keys=keys)
      
            0       1       2       3
        PRICE   PRICE   PRICE   PRICE
      0   100   200.0   300.0   400.0
      1   200   300.0   400.0   500.0
      2   300   400.0   500.0   600.0
      3   400   500.0   600.0   700.0
      4   500   600.0   700.0   800.0
      5   600   700.0   800.0   900.0
      6   700   800.0   900.0  1000.0
      7   800   900.0  1000.0     NaN
      8   900  1000.0     NaN     NaN
      9  1000     NaN     NaN     NaN
      

      如果您将concat 分配给df_c

      keys = range(horizon + 1)
      df_c = pd.concat([df.shift(-i) for i in keys], axis=1, keys=keys)
      
      df_c.apply(lambda x: pd.Series([x[0].values, x[1:].values]), axis=1)
      
                0                       1
      0   [100.0]   [200.0, 300.0, 400.0]
      1   [200.0]   [300.0, 400.0, 500.0]
      2   [300.0]   [400.0, 500.0, 600.0]
      3   [400.0]   [500.0, 600.0, 700.0]
      4   [500.0]   [600.0, 700.0, 800.0]
      5   [600.0]   [700.0, 800.0, 900.0]
      6   [700.0]  [800.0, 900.0, 1000.0]
      7   [800.0]    [900.0, 1000.0, nan]
      8   [900.0]      [1000.0, nan, nan]
      9  [1000.0]         [nan, nan, nan]
      

      【讨论】:

      • 您认为在哪种情况下会带来性能优势?
      • @lukewitmer 不,我刚刚跑了%%timeit,你的 wat 快了 5 倍以上。我喜欢我的方式,因为我觉得它更优雅。但我会选择你的方式,因为它非常直观且速度更快。
      猜你喜欢
      • 2014-07-04
      • 2020-09-08
      • 2018-11-13
      • 1970-01-01
      • 2022-01-04
      • 1970-01-01
      • 2013-08-10
      • 1970-01-01
      相关资源
      最近更新 更多