使用 base::cumsum 将组内的最大值保持在组内不变

Keeping the max within a group constant within a group using base::cumsum

使用下面的数据使 cumsum_a 列看起来像 should 列。

开头的数据:

> demo
    th seq group
1 20.1   1    10
2 24.1   2    10
3 26.1   3    10
4  1.1   1    20
5  2.1   2    20
6  4.1   3    20

下面的“应该”栏是目标。

demo<-data.frame(th=c(c(20.1,24.1,26.1),(c(1.1,2.1,4.1))),
    seq=(c(1:3,1:3)),group=c(rep(10,3),rep(20,3)))

library(magrittr)
library(dplyr)

demo %>% 
    group_by(group) %>%
        mutate(
    cumsum_a= cumsum((group)^seq*
            (((th)/cummax(th)))))%>%  
        ungroup()%>%
        mutate(.,
  cumsum_m=c( #As an example only, this manually does exactly what cumsum_a is doing (which is wrong)
        10^1*20.1/20.1,   #good
        10^1*20.1/20.1 + 10^2*24.1/24.1,            #different denominators, bad       
        10^1*20.1/20.1 + 10^2*24.1/24.1 + 10^3*26.1/26.1, #different denominators, bad
        20^1*1.1/1.1, #good
        20^1*1.1/1.1 + 20^2*2.1/2.1, #different denominators, bad
        20^1*1.1/1.1 + 20^2*2.1/2.1 + 20^3*4.1/4.1 #different denominators, bad
    ),
  should=c( #this is exactly the kind of calculation I want
        10^1*20.1/20.1,  #good
        10^1*20.1/24.1 + 10^2*24.1/24.1,        #good
        10^1*20.1/26.1 + 10^2*24.1/26.1 + 10^3*26.1/26.1, #good
        20^1*1.1/1.1, #good
        20^1*1.1/2.1 + 20^2*2.1/2.1, #good
        20^1*1.1/4.1 + 20^2*2.1/4.1 + 20^3*4.1/4.1 #good
    )

)

最简单地说,每行的分母必须相同,因此在 cumsum_m 的第二行或 cumsum_a 的基础计算中使用 24.1 和 24.1 而不是 20.1 和 24.1。

这是新列,其中 shouldcumsum_acumsum_m 应该的内容。

     th   seq group cumsum_a cumsum_m should
  <dbl> <int> <dbl>    <dbl>    <dbl>  <dbl>
1  20.1     1    10       10       10    10 
2  24.1     2    10      110      110   108.
3  26.1     3    10     1110     1110  1100.
4   1.1     1    20       20       20    20 
5   2.1     2    20      420      420   410.
6   4.1     3    20     8420     8420  8210.

您可以使用以下解决方案:

  • purrr::accumulate有一个二元函数,第一个用.x..1表示的是前面迭代的累加值,.y表示我们向量的当前值 (2:n())。因此,我们的第一个累加值将是 group 值的第一个元素,因为我将其作为 .init 参数
  • 提供
  • 因为你想改变之前迭代/计算的分母,所以我将结果.x乘以cmax的先前值与[=19的当前值的比率=]

我认为剩下的部分已经很清楚了,但如果您对此有任何疑问,请告诉我。

library(dplyr)
library(purrr)

demo %>%
  group_by(group) %>%
  mutate(cmax = cummax(th), 
         should = accumulate(2:n(), .init = group[1], 
                             ~ (.x * cmax[.y - 1] / cmax[.y]) + (group[.y] ^ seq[.y]) * (th[.y] / cmax[.y])))

# A tibble: 6 x 5
# Groups:   group [2]
     th   seq group  cmax should
  <dbl> <int> <dbl> <dbl>  <dbl>
1  20.1     1    10  20.1    10 
2  24.1     2    10  24.1   108.
3  26.1     3    10  26.1  1100.
4   1.1     1    20   1.1    20 
5   2.1     2    20   2.1   410.
6   4.1     3    20   4.1  8210.