考虑先前计算的值,迭代计算变量中的值

问题描述 投票:0回答:1

在处理 2023 年代码降临第 9 天的编码选项时出现了这个问题。假设我们有一个列表 col 对象,其中一列包含 tibbles。每个小标题都有一个变量

aa
。目标是一个新变量
bb
,它是当下面所有
aa
值为零时
aa
的值。从那时起,
bb
将被计算为:
aa + lead(bb)
;即从当前行开始将
aa
与下面一行的
bb
相加。

这是一个可重现的示例:

dat <- tibble(
  V1 = sample(LETTERS, 3),
  V2 = rnorm(3, 100, 50),
  V3 = list(
    tibble(var_not_used = sample(LETTERS, 5), aa = c(15, 3, 0, 0 ,0)),
    tibble(var_not_used = sample(LETTERS, 5), aa = c(21, 6, 1, 0, 0)),
    tibble(var_not_used = sample(LETTERS, 5), aa = c(45, 15, 6, 2, 0))
  )
  )
小标题 1 中的

bb
应该是
18, 3, 0, 0, 0
;小标题 2 中的
bb
应该是
28, 7, 1, 0, 0
;小标题 3 中的
bb
应该是
68, 23, 8, 2, 0
。下面是一个尝试/说明它应该朝哪个方向发展。

我们怎样才能优雅地编写代码以仅获得一列

bb
?我对 tidyverse 解决方案特别感兴趣;取消嵌套是一个选项,但如果解决方案直接作用于嵌套对象,那就太好了。

dat <- tibble(
  V1 = sample(LETTERS, 3),
  V2 = rnorm(3, 100, 50),
  V3 = list(
    tibble(var_not_used = sample(LETTERS, 5), aa = c(15, 3, 0, 0 ,0)),
    tibble(var_not_used = sample(LETTERS, 5), aa = c(21, 6, 1, 0, 0)),
    tibble(var_not_used = sample(LETTERS, 5), aa = c(45, 15, 6, 2, 0))
  )
  ) %>% 
  ## from here on: this returns the data that we are interested in; however,
  ## its a lot of code repetition and many new columns. Moreover, in reality
  ## we might face situations in which we had to do way more than 4 of these
  ## mutate's
  mutate(
    V3 = map(V3,  ~ .x %>% 
               mutate(bb1 = case_when(
                 lead(aa) == 0 ~ aa + lead(aa, default = 0)
                 ))
             )
    ) %>% 
  mutate(
    V3 = map(V3,  ~ .x %>% 
               mutate(bb2 = case_when(
                 is.na(bb1) ~ aa + lead(bb1, default = 0)
                 ))
             )
    )  %>% 
  mutate(
    V3 = map(V3,  ~ .x %>% 
               mutate(bb3 = case_when(
                 is.na(bb2) ~ aa + lead(bb2, default = 0)
                 ))
             )
    ) %>% 
  mutate(
    V3 = map(V3,  ~ .x %>% 
               mutate(bb4 = case_when(
                 is.na(bb3) ~ aa + lead(bb3, default = 0)
                 ))
             )
    )
r tidyverse
1个回答
0
投票

看起来

bb
只是
aa
的逆累加和,所以我们可以这样做:

dat %>%
  mutate(V3 = map(V3, ~ .x %>% mutate(bb = rev(cumsum(rev(aa))))))

我们可以通过拉出列表列来查看它的样子:

dat %>%
  mutate(V3 = map(V3, ~ .x %>% mutate(bb = rev(cumsum(rev(aa)))))) %>%
  pluck('V3')
#> [[1]]
#> # A tibble: 5 x 3
#>   var_not_used    aa    bb
#>   <chr>        <dbl> <dbl>
#> 1 W               15    18
#> 2 K                3     3
#> 3 G                0     0
#> 4 Q                0     0
#> 5 F                0     0
#> 
#> [[2]]
#> # A tibble: 5 x 3
#>   var_not_used    aa    bb
#>   <chr>        <dbl> <dbl>
#> 1 P               21    28
#> 2 O                6     7
#> 3 A                1     1
#> 4 W                0     0
#> 5 M                0     0
#> 
#> [[3]]
#> # A tibble: 5 x 3
#>   var_not_used    aa    bb
#>   <chr>        <dbl> <dbl>
#> 1 M               45    68
#> 2 B               15    23
#> 3 Y                6     8
#> 4 A                2     2
#> 5 T                0     0
© www.soinside.com 2019 - 2024. All rights reserved.