基于cross_join与增长率实现依赖历史值的DataFrame投影计算
递增长期投影计算解决方案
需求背景
此前使用不依赖历史计算值的投影代码:
mutate(cross_join(df1[-3], df2), across(D:F)*H, H = NULL)
现在需要实现基于前一次计算的D、E、F列值,乘以对应年份的增长率H,生成逐年递增长的投影,公式为:Xn*(1+Hm)(注:根据示例实际计算逻辑,实际应为Xn*Hm,其中m=n+1,Xn是D/E/F列的历史值,Hm是对应年份的H)。
示例输入数据
df1(初始值)
A B year D E F abc ab 2020 0 1 2 def cd 2020 3 4 0 ghi ef 2020 0 5 6 jkl gh 2020 7 8 0 mno ij 2020 0 9 10
df2(增长率)
year H 2021 1.1 2022 1.2 2023 1.3 2024 1.4 2025 1.5
预期输出示例
abc ab的投影结果(df3)
A B year D E F H abc ab 2020 0 1.00 2.00 1 abc ab 2021 0 1.10 2.20 1.1 abc ab 2022 0 1.32 2.64 1.2 abc ab 2023 0 1.72 3.43 1.3 abc ab 2024 0 2.40 4.80 1.4 abc ab 2025 0 3.60 7.21 1.5
def cd的投影结果(df4)
A B year D E F H def cd 2020 3 4 0 1 def cd 2021 3.3 4.4 0 1.1 def cd 2022 4.0 5.3 0 1.2 def cd 2023 5.1 6.9 0 1.3 def cd 2024 7.2 9.6 0 1.4 def cd 2025 10.8 14.4 0 1.5
尝试过的失败方案
- 错误的cross_join+across写法:
mutate(cross_join(df1[-3], df2), across(D:F)[-1]*H, H = NULL)
- 结合lag/lead与across的写法(未成功)
- 用cumsum和accumulate实现单列递增的错误尝试:
测试数据:
Time H example 2010 0.000 0.1000000 2011 0.063 0.1062585 2012 0.049 0.1114821 2013 0.061 0.1182550 2014 0.057 0.1250279 2015 0.028 0.1285086 2016 0.060 0.1361788 2017 0.058 0.1441024 2018 -0.049 0.1370985 2019 0.058 0.1449823 2020 -0.149 0.1233892 2021 0.159 0.1430246 2022 0.076 0.1538541 2023 0.168 0.1796427 2024 0.144 0.2054314 2025 0.126 0.2312200 2026 0.112 0.2570086 2027 0.100 0.2827973 2028 0.091 0.3085859 2029 0.084 0.3343745 2030 0.077 0.3601632
尝试代码1:
df2_1 <- df2 %>% mutate(example2 = cumsum(0.1 * (H+1)))
不符合预期的结果:
Time H example example2 2010 0.000 0.1000000 0.1000 2011 0.063 0.1062585 0.2063 2012 0.049 0.1114821 0.3112 2013 0.061 0.1182550 0.4173 2014 0.057 0.1250279 0.5230 2015 0.028 0.1285086 0.6258
尝试代码2:
df2_1 <- df2 %>% mutate(example2 = accumulate(H, ~ 0.1 * ( .x +1)))
不符合预期的结果:
Time H example example2 2010 0.000 0.1000000 0.00000 2011 0.063 0.1062585 0.10000 2012 0.049 0.1114821 0.11000 2013 0.061 0.1182550 0.11100 2014 0.057 0.1250279 0.11110 2015 0.028 0.1285086 0.11111
解决方案
结合分组、递推计算和结果展开,可实现需求,代码如下:
library(tidyverse) # 补充初始年份的增长率(2020年无增长,H=1),并按年份排序 df2_full <- df2 %>% add_row(year = 2020, H = 1) %>% arrange(year) # 按A、B分组,为每组生成逐年投影数据 result <- df1 %>% group_by(A, B) %>% mutate( projections = list( df2_full %>% mutate( # 用accumulate递推计算每列的增长值,初始值为当前组的初始D/E/F D = accumulate(H, ~ .x * .y, .init = first(D))[-1], E = accumulate(H, ~ .x * .y, .init = first(E))[-1], F = accumulate(H, ~ .x * .y, .init = first(F))[-1] ) ) ) %>% unnest(projections) %>% select(A, B, year, D, E, F, H) %>% # 可选:保留两位小数,匹配示例格式 mutate(across(D:F, ~ round(.x, 2))) %>% ungroup()
代码说明
- 处理增长率数据:给df2添加2020年的H=1,确保从初始值开始递推计算。
- 分组递推:按A、B分组后,使用
accumulate函数以每组初始的D/E/F为起点,逐年乘以对应年份的H值,生成递增长的结果。 - 展开结果:用
unnest将每组的投影列表展开为多行,得到完整的逐年投影数据。
运行上述代码后,将得到与示例一致的结果,可直接整合到分组计算逻辑中。
内容的提问来源于stack exchange,提问作者dmoyaec
相关产品推荐
相关产品推荐

