【问题标题】:Calculate cumulative column with calculation用计算计算累积列
【发布时间】:2020-12-17 03:35:02
【问题描述】:

我有以下数据框:

data = {'month': {0: Timestamp('2019-01-01 00:00:00'),
  1: Timestamp('2019-02-01 00:00:00'),
  2: Timestamp('2019-03-01 00:00:00'),
  3: Timestamp('2019-04-01 00:00:00'),
  4: Timestamp('2019-05-01 00:00:00')},
 'base_expenses': {0: 200.0, 1: 200.0, 2: 200.0, 3: 200.0, 4: 200.0},
 'base_contribution': {0: 100.0, 1: 100.0, 2: 100.0, 3: 100.0, 4: 100.0}}

df = pd.DataFrame(data)
df

month   base_expenses   base_contribution
0   2019-01-01  200.0   100.0
1   2019-02-01  200.0   100.0
2   2019-03-01  200.0   100.0
3   2019-04-01  200.0   100.0
4   2019-05-01  200.0   100.0

此数据将代表一项投资,该投资每个月都会增加额外的贡献,并且每个月都会以一定的百分比增长。

例如,投资的起始余额为50000。每个月我们都会在余额中添加base_contribution。最后,余额每个月都会增长0.6%

我可以使用如下循环计算所有这些:

CURRENT_BALANCE = 50000
MONTHLY_INVESTMENT_RETURN = 0.006

df['base_balance'] = CURRENT_BALANCE
for index, row in df.iterrows():
    if index == 0:
        balance = row['base_contribution'] + row['base_balance']
        balance += balance * MONTHLY_INVESTMENT_RETURN
        df.loc[row.name, 'base_balance'] = balance
    else:
        balance = row['base_contribution'] + df.loc[row.name - 1, 'base_balance']
        balance += balance * MONTHLY_INVESTMENT_RETURN
        df.loc[row.name, 'base_balance'] = balance

结果是:

    month   base_expenses   base_contribution   base_balance
0   2019-01-01  200.0   100.0   50422.344909
1   2019-02-01  200.0   100.0   50847.407197
2   2019-03-01  200.0   100.0   51275.204349
3   2019-04-01  200.0   100.0   51705.753960
4   2019-05-01  200.0   100.0   52139.073741

我正在处理的真实数据非常大,因此我希望尽可能避免这种循环方法。有没有办法在矢量化庄园或不循环的情况下做到这一点?

【问题讨论】:

  • 根据您的代码,第一行我得到: (50000+100)*1.006 = 50400.6 。所以我不明白你是怎么得到 50422.344909 的。
  • 大概用numpy写代码,用numba加速
  • @IsmaelELATIFI 这是因为为了简单起见,我将 MONTHLY_INVESTMENT_RETURN 舍入到小数点后 3 位。实际数字是 0.00643403011000343。我为混乱道歉,但问题的核心仍然存在。
  • 好的,我明白了。顺便说一句,这里的向量化没有意义,因为您的计算是顺序的,即您需要计算第 N 行才能计算第 N+1 行。所以因为它不能并行化,所以不值得矢量化。
  • 哦,好的,有道理,好点。谢谢。

标签: python pandas


【解决方案1】:

按照这个post看来是不可行的

您可以在每个循环中保存一个if。而df.at 也是一种在数据框中设置值的更快方式。

balance = df.loc[0, 'base_contribution'] + df.loc[0, 'base_balance']
balance += balance * MONTHLY_INVESTMENT_RETURN
df.at[0, 'base_balance'] = balance

for index, row in df[1:].iterrows():
    balance = row['base_contribution'] + df.loc[row.name - 1, 'base_balance']
    balance += balance * MONTHLY_INVESTMENT_RETURN
    df.at[index, 'base_balance'] = balance

我发现了有趣的方法:rollingcumsumexpanding。但是这里没有任何效果,因为我们不知道启动时 base_contribution 的值。

【讨论】:

    【解决方案2】:

    假设 base_balance 是常数。

    只需一个中间步骤,您就可以做您想做的事: 请记住,您可以将投资分成几部分并计算每个部分的回报。

    所以第n个月时的起始余额(CURRENT_BALANCE)的结果值可以写成:

    df["result_on_start_investment"] =  CURRENT_BALANCE * math.pow(MONTHLY_INVESTMENT_RETURN,  np.arange(len(df)) + 1)
    

    每个月都会向投资中增加一笔额外金额。这个金额每个月都会得到回报。作为第一步计算

    df["result_on_added_at_month_one"] = base_balance * math.pow(MONTHLY_INVESTMENT_RETURN,  np.arange(len(df)) + 1)
    

    最后因为在第 n-1 个月增加货币的收入等于在第 1 个月在第 2 个月增加货币的收入:

    df["balance"] = df["result_on_start_investment"] + df["result_on_added_at_month_one"].cumsum()
    

    结果:

    month  base_expenses  base_contribution  n  result_on_added_at_month_one  result_on_start_investment       balance
    0      0          200.0              100.0  1                    100.643403                50321.701506  50422.344909
    1      1          200.0              100.0  2                    101.290946                50645.472848  50847.407197
    2      2          200.0              100.0  3                    101.942655                50971.327345  51275.204349
    3      3          200.0              100.0  4                    102.598557                51299.278400  51705.753960
    4      4          200.0              100.0  5                    103.258679                51629.339502  52139.073741
    

    【讨论】:

      猜你喜欢
      • 2019-06-06
      • 1970-01-01
      • 2018-03-26
      • 2020-07-18
      • 1970-01-01
      • 1970-01-01
      • 2015-09-07
      • 2019-10-07
      • 2020-11-04
      相关资源
      最近更新 更多