尝试在 IF 语句中使用 Lag 函数来添加前几行相同的值并且代码不起作用

Trying to use Lag function in a IF statement to add the previous rows same value and Code not working

关于以下数据:

wpd c_days  c_days_ct   cd_days_ct_r
-72.88  0   0       0
-56     0   0       0
-0.49   1   1       1
-32.41  0   0       0
-83.69  0   0       0
-53.15  0   0       0
-0.42   1   1       1
-52.32  0   0       0
-26.37  0   0       0
-45.57  0   0       0
-23.62  0   0       0
-1.22   1   1       1
-23.94  0   0       0
-0.13   1   1       1
-13.81  1   2       1
-9.58   1   3       1
0      1    4       1
-1.95   1   5       1
-8.85   1   6       1
-15.66  1   7       1
-15.87  1   8       1
-53.94  0   0       0
-91.84  0   0       0
-58.89  0   0       0
-61.52  0   0       0

我想做什么

  1. 根据 WPD (>=-20) 的值计算 c_days 并将其设置为 1(下面代码的第 1 行)

  2. 以上数据显示cd_days_ct(来自excel)并且正在检查当前行值是否为c_days,如果是,则来自之前的值c_days_ct,加1。我正在尝试计算c_days = 1 连续次数的滚动计数器

  3. 我正在尝试通过下面代码的第 3 行(使用滞后)来执行此操作 我必须添加代码的第 2 行来创建 c_days_ct,因为如果丢失,就会出现错误(如下) 错误:mutate() 输入 cdays_ct 有问题。 x 对象 'cdays_ct' 未找到

  4. 但是 c_days_ct_r 从未递增到 1 以上,我不明白为什么

     mutate(cdays=ifelse(wpd>=-20,1,0)) %>% 
     mutate(cdays_ct=0) %>% 
     mutate(cdays_ct=if_else(cdays==1,lag(cdays_ct,1)+1,0))
    

可能是我缺少的一些基本东西,但我已经用头撞墙两天了

这里有一个选项rle

library(dplyr)
df2 <- df1 %>%
    mutate(c_days1 = as.integer(wpd >= -20),
          c_days_ct1 = with(rle(c_days1), 
          sequence(lengths)* rep(values, lengths)), 
      cd_days_ct_r1 = +(c_days_ct1 > 0))

-输出

df2
#        wpd c_days c_days_ct cd_days_ct_r c_days1 c_days_ct1 cd_days_ct_r1
#1  -72.88      0         0            0       0          0             0
#2  -56.00      0         0            0       0          0             0
#3   -0.49      1         1            1       1          1             1
#4  -32.41      0         0            0       0          0             0
#5  -83.69      0         0            0       0          0             0
#6  -53.15      0         0            0       0          0             0
#7   -0.42      1         1            1       1          1             1
#8  -52.32      0         0            0       0          0             0
#9  -26.37      0         0            0       0          0             0
#10 -45.57      0         0            0       0          0             0
#11 -23.62      0         0            0       0          0             0
#12  -1.22      1         1            1       1          1             1
#13 -23.94      0         0            0       0          0             0
#14  -0.13      1         1            1       1          1             1
#15 -13.81      1         2            1       1          2             1
#16  -9.58      1         3            1       1          3             1
#17   0.00      1         4            1       1          4             1
#18  -1.95      1         5            1       1          5             1
#19  -8.85      1         6            1       1          6             1
#20 -15.66      1         7            1       1          7             1
#21 -15.87      1         8            1       1          8             1
#22 -53.94      0         0            0       0          0             0
#23 -91.84      0         0            0       0          0             0
#24 -58.89      0         0            0       0          0             0
#25 -61.52      0         0            0       0          0             0

注意:列名末尾带有后缀1的是新创建的列。保留输入中的其他列以进行交叉检查


或者另一种选择是根据 'c_days' 列中的 difference 创建一个分组变量

df1 %>%
      mutate(c_days = as.integer(wpd >= -20)) %>% 
      group_by(grp = cumsum(c(TRUE, diff(c_days) > 0))) %>% 
      mutate(c_days_ct1 = row_number() * c_days) %>% 
      ungroup %>% 
      select(-grp) %>%
      as.data.frame

-输出

#        wpd c_days c_days_ct cd_days_ct_r c_days_ct1
#1  -72.88      0         0            0          0
#2  -56.00      0         0            0          0
#3   -0.49      1         1            1          1
#4  -32.41      0         0            0          0
#5  -83.69      0         0            0          0
#6  -53.15      0         0            0          0
#7   -0.42      1         1            1          1
#8  -52.32      0         0            0          0
#9  -26.37      0         0            0          0
#10 -45.57      0         0            0          0
#11 -23.62      0         0            0          0
#12  -1.22      1         1            1          1
#13 -23.94      0         0            0          0
#14  -0.13      1         1            1          1
#15 -13.81      1         2            1          2
#16  -9.58      1         3            1          3
#17   0.00      1         4            1          4
#18  -1.95      1         5            1          5
#19  -8.85      1         6            1          6
#20 -15.66      1         7            1          7
#21 -15.87      1         8            1          8
#22 -53.94      0         0            0          0
#23 -91.84      0         0            0          0
#24 -58.89      0         0            0          0
#25 -61.52      0         0            0          0

或者另一种选择是使用 accumulate

递归更新
library(purrr)
df1 %>% 
    mutate(c_days = +( wpd >= -20),
    c_days_ct1 = accumulate(c_days, ~ if(.y == 1) .x + .y else .y))

或使用 base RReduce

Reduce(function(x, y) if(y == 1) x + y else y, 
        +(df1$wpd >= -20), accumulate = TRUE)
#[1] 0 0 1 0 0 0 1 0 0 0 0 1 0 1 2 3 4 5 6 7 8 0 0 0 0

数据

df1 <- structure(list(wpd = c(-72.88, -56, -0.49, -32.41, -83.69, -53.15, 
-0.42, -52.32, -26.37, -45.57, -23.62, -1.22, -23.94, -0.13, 
-13.81, -9.58, 0, -1.95, -8.85, -15.66, -15.87, -53.94, -91.84, 
-58.89, -61.52), c_days = c(0L, 0L, 1L, 0L, 0L, 0L, 1L, 0L, 0L, 
0L, 0L, 1L, 0L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 0L, 0L, 0L, 0L
), c_days_ct = c(0L, 0L, 1L, 0L, 0L, 0L, 1L, 0L, 0L, 0L, 0L, 
1L, 0L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 0L, 0L, 0L, 0L), cd_days_ct_r = c(0L, 
0L, 1L, 0L, 0L, 0L, 1L, 0L, 0L, 0L, 0L, 1L, 0L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 0L, 0L, 0L, 0L)), class = "data.frame", row.names = c(NA, 
-25L))

这是一个使用 rleid

data.table 选项
setDT(df)[
  ,
  c_days := +(wpd >= -20)
][
  ,
  c_days_ct := seq_along(c_days) * c_days,
  rleid(c_days)
]

这给出了

> df
       wpd c_days c_days_ct
 1: -72.88      0         0
 2: -56.00      0         0
 3:  -0.49      1         1
 4: -32.41      0         0
 5: -83.69      0         0
 6: -53.15      0         0
 7:  -0.42      1         1
 8: -52.32      0         0
 9: -26.37      0         0
10: -45.57      0         0
11: -23.62      0         0
12:  -1.22      1         1
13: -23.94      0         0
14:  -0.13      1         1
15: -13.81      1         2
16:  -9.58      1         3
17:   0.00      1         4
18:  -1.95      1         5
19:  -8.85      1         6
20: -15.66      1         7
21: -15.87      1         8
22: -53.94      0         0
23: -91.84      0         0
24: -58.89      0         0
25: -61.52      0         0
       wpd c_days c_days_ct

数据

> dput(df)
structure(list(wpd = c(-72.88, -56, -0.49, -32.41, -83.69, -53.15,
-0.42, -52.32, -26.37, -45.57, -23.62, -1.22, -23.94, -0.13,
-13.81, -9.58, 0, -1.95, -8.85, -15.66, -15.87, -53.94, -91.84,
-58.89, -61.52)), row.names = c(NA, -25L), class = "data.frame")