【问题标题】:Apply rolling function on pandas dataframe with multiple arguments在具有多个参数的 pandas 数据帧上应用滚动函数
【发布时间】:2020-04-21 19:16:11
【问题描述】:

我正在尝试在 pandas 数据框上应用滚动函数,窗口为 3 年。

import pandas as pd

# Dummy data
df = pd.DataFrame({'Product': ['A', 'A', 'A', 'A', 'B', 'B', 'B', 'B'],
                   'Year': [2015, 2016, 2017, 2018, 2015, 2016, 2017, 2018],
                   'IB': [2, 5, 8, 10, 7, 5, 10, 14],
                   'OB': [5, 8, 10, 12, 5, 10, 14, 20],
                   'Delta': [2, 2, 1, 3, -1, 3, 2, 4]})

# The function to be applied
def get_ln_rate(ib, ob, delta):
    n_years = len(ib)
    return sum(delta)*np.log(ob[-1]/ib[0]) / (n_years * (ob[-1] - ib[0]))

预期的输出是

  Product  Year  IB  OB  Delta  Ln_Rate
0       A  2015   2   5      2     
1       A  2016   5   8      2    
2       A  2017   8  10      1   0.3353
3       A  2018  10  12      3   0.2501
4       B  2015   7   5     -1  
5       B  2016   5  10      3
6       B  2017  10  14      2   0.1320
7       B  2018  14  20      4   0.2773

我试过了

df['Ln_Rate'] = df.groupby('Product').rolling(3).apply(lambda x: get_ln_rate(x['IB'], x['OB'], x['Delta']))

但这不起作用。

我找到了几个类似的帖子

applying custom rolling function to dataframe - 这个没有明确的答案

Pandas Rolling Apply custom - 这个没有多个参数

apply custom function on pandas dataframe on a rolling window - 这个有rolling.apply...但它没有显示语法。

似乎两者都不是。任何指向正确语法的指针将不胜感激。

【问题讨论】:

    标签: python pandas pandas-groupby rolling-computation


    【解决方案1】:

    我通过重用滚动窗口解决了这个问题。

    import numpy as np
    
    WINDOW_SIZE = 3
    
    rw = df.groupby('Product').rolling(WINDOW_SIZE)
    
    df = df.assign(delta_sum=rw['Delta'].agg(np.sum).reset_index()['Delta'],
                   ib_first=rw['IB'].apply(lambda xs: xs[0]).reset_index()['IB'],
                   ob_last=rw['OB'].apply(lambda xs: xs[-1]).reset_index()['OB'])
    
    df['ln_rate'] = df['delta_sum']*np.log(df['ob_last']/df['ib_first']) / (WINDOW_SIZE * (df['ob_last'] - df['ib_first']))
    

    产量:

      Product  Year  IB  OB  Delta  delta_sum  ib_first  ob_last   ln_rate
    0       A  2015   2   5      2        NaN       NaN      NaN       NaN
    1       A  2016   5   8      2        NaN       NaN      NaN       NaN
    2       A  2017   8  10      1        5.0       2.0     10.0  0.335300
    3       A  2018  10  12      3        6.0       5.0     12.0  0.250134
    4       B  2015   7   5     -1        NaN       NaN      NaN       NaN
    5       B  2016   5  10      3        NaN       NaN      NaN       NaN
    6       B  2017  10  14      2        4.0       7.0     14.0  0.132028
    7       B  2018  14  20      4        9.0       5.0     20.0  0.277259
    

    重置索引是必要的,以将分组的 DataFrame 转换回其初始形状。

    希望对您有所帮助。

    【讨论】:

    • 嗨。谢谢。这是一个很好的答案。它并没有真正回答如何应用具有多个参数的自定义函数。但它确实展示了一种组合单参数函数以实现所需结果的聪明方法。
    【解决方案2】:

    我想到了另一个答案:在分组索引上创建滚动窗口,并将部分 dfs 传递给您的自定义函数。当然,该函数并不完全是使用多个参数调用的,而是使用了所有需要的数据。

    import numpy as np
    import pandas as pd
    
    df = pd.DataFrame({'Product': ['A', 'A', 'A', 'A', 'B', 'B', 'B', 'B'],
                       'Year': [2015, 2016, 2017, 2018, 2015, 2016, 2017, 2018],
                       'IB': [2, 5, 8, 10, 7, 5, 10, 14],
                       'OB': [5, 8, 10, 12, 5, 10, 14, 20],
                       'Delta': [2, 2, 1, 3, -1, 3, 2, 4]})
    
    # The function to be applied
    def get_ln_rate(df):
        n_years = len(df['IB'])
        return df['Delta'].sum() * np.log(df['OB'].iloc[-1] / df['IB'].iloc[0]) / (n_years * (df['OB'].iloc[-1] - df['IB'].iloc[0]))
    
    ln_rate = df.groupby('Product').apply(lambda grp: pd.Series(grp.index).rolling(3).agg({'Ln_Rate': lambda window: get_ln_rate(grp.loc[window])})).reset_index()['Ln_Rate']
    df.assign(Ln_Rate=ln_rate)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-04-23
      • 1970-01-01
      • 2020-12-07
      • 1970-01-01
      • 2021-03-09
      • 2021-01-11
      • 2017-06-17
      相关资源
      最近更新 更多