【问题标题】:Creating cumulative product with reset to 1 at each end of the month在每个月末创建累积产品并重置为 1
【发布时间】:2023-01-23 19:36:17
【问题描述】:

我尝试在 Dataframe df 中创建一个新列 CumReturn,其中包含一个月的累计产品。我尝试在每个月末将 cum_prod() 重置为 1(如果 EndMonth == 1)并从新的累积产品开始。

df:
Date        EndMonth  ID1  Return
2023-01-30     0       A     0.95
2023-01-30     0       B     0.98
2023-01-31     1       A     1.01
2023-01-31     1       B     1.02
2023-02-01     0       A     1.05
2023-02-01     0       B     0.92
2023-02-02     0       A     0.97
2023-02-02     0       B     0.99

我试着用它来做: df['CumReturn'] = np.where(df['EndMonth'] == 1, 1, df['Return'].groupby('ID1').cumprod())

当我这样做时,我得到了2023-02-02整个时期的累计产品,而不仅仅是自 2 月初以来。

对于可重复性:

import pandas as pd
df1 = pd.DataFrame({
    'Date':['2023-01-30', '2023-01-30', '2023-01-31', '2023-01-31', '2023-02-01', '2023-02-01', '2023-02-02', '2023-02-02'],
    'EndMonth':[0, 0, 1, 1, 0, 0, 0, 0],
    'ID1':['A', 'B', 'A', 'B', 'A', 'B', 'A', 'B'],
    'Return':[0.95, 0.98, 1.01, 1.02, 1.05, 0.92, 0.97, 0.99]})
df1 = df1.set_index('Date')

非常感谢!

【问题讨论】:

  • 为了清楚起见,您能否提供预期的输出?

标签: python pandas


【解决方案1】:

看起来你想要:

# set up grouper per ID and month
g = df1.groupby(['ID1', pd.to_datetime(df1.index).month])['Return']

# get cumprod per month with starting value being 1
# (we divide by the first value)
df1['CumProd'] = g.cumprod().div(g.transform('first'))

输出:

            EndMonth ID1  Return  CumProd
Date                                     
2023-01-30         0   A    0.95     1.00
2023-01-30         0   B    0.98     1.00
2023-01-31         1   A    1.01     1.01
2023-01-31         1   B    1.02     1.02
2023-02-01         0   A    1.05     1.00
2023-02-01         0   B    0.92     1.00
2023-02-02         0   A    0.97     0.97
2023-02-02         0   B    0.99     0.99

【讨论】:

    【解决方案2】:

    IIUC 使用:

    df1.index = pd.to_datetime(df1.index)
    
    df1['CumReturn'] = (df1['Return'].add(1)
                                     .groupby([df1['ID1'], df1.index.to_period('m')])
                                     .cumprod()
                                     .sub(1))
    print (df1)
                EndMonth ID1  Return  CumReturn
    Date                                       
    2023-01-30         0   A    0.95     0.9500
    2023-01-30         0   B    0.98     0.9800
    2023-01-31         1   A    1.01     2.9195
    2023-01-31         1   B    1.02     2.9996
    2023-02-01         0   A    1.05     1.0500
    2023-02-01         0   B    0.92     0.9200
    2023-02-02         0   A    0.97     3.0385
    2023-02-02         0   B    0.99     2.8208
    

    【讨论】:

      猜你喜欢
      • 2021-01-04
      • 2017-03-07
      • 1970-01-01
      • 2019-03-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-21
      相关资源
      最近更新 更多