按行删除某些特定索引之前的值

Removing values prior to some specific index rowwise

我目前的数据如下所示:

ID Var_1 Var_2 Var_3 Var_4 Var_5 RemovePrior
1 20 30 25 35 40 3
2 40 50 45 55 60 2
3 60 70 65 75 80 4
4 80 90 85 95 85 5
df <- data.frame(ID = c(1, 2, 3, 4),
                 Var_1 = c(20, 40, 60, 80),
                 Var_2 = c(30, 50, 70, 90),
                 Var_3 = c(25, 45, 65, 85),
                 Var_4 = c(35, 55, 75, 95),
                 Var_5 = c(40, 60, 80, 85),
                 RemovePrior = c(3, 2, 4, 5))

我的目标是——对于每一行——用带有 NA 的“RemovePrior”表示的后缀填充变量左侧的变量。例如,对于 ID = 1,RemovePrior 的值为 3,因此我希望将 Var_1 和 Var_2 设置为 NA。以下是预期结果:

ID Var_1 Var_2 Var_3 Var_4 Var_5 RemovePrior
1 NA NA 25 35 40 3
2 NA 50 45 55 60 2
3 NA NA NA 75 80 4
4 NA NA NA NA 85 5

可能的解决方案:

library(tidyverse)

df %>% 
  mutate(across(Var_1:Var_5,
    ~ if_else(which(cur_column() == names(df[-1])) < RemovePrior, NA_real_, .x)))

#>   ID Var_1 Var_2 Var_3 Var_4 Var_5 RemovePrior
#> 1  1    NA    NA    25    35    40           3
#> 2  2    NA    50    45    55    60           2
#> 3  3    NA    NA    NA    75    80           4
#> 4  4    NA    NA    NA    NA    85           5

我们可以使用base R

nm1 <- startsWith(names(df), "Var")
df[nm1] <- NA^(col(df[nm1]) < df$RemovePrior) * df[nm1]

-输出

> df
  ID Var_1 Var_2 Var_3 Var_4 Var_5 RemovePrior
1  1    NA    NA    25    35    40           3
2  2    NA    50    45    55    60           2
3  3    NA    NA    NA    75    80           4
4  4    NA    NA    NA    NA    85           5

dplyr

library(dplyr)
df %>% 
   mutate(across(starts_with("Var_"), 
   ~ case_when(readr::parse_number(cur_column()) >= RemovePrior ~ .x )))
  ID Var_1 Var_2 Var_3 Var_4 Var_5 RemovePrior
1  1    NA    NA    25    35    40           3
2  2    NA    50    45    55    60           2
3  3    NA    NA    NA    75    80           4
4  4    NA    NA    NA    NA    85           5

这是我们可以做到的另一种方法: 使用 pivot_longerpivot_wider

library(dplyr)
library(tidyr)

df %>% 
  pivot_longer(
    -c(ID, RemovePrior)
  ) %>% 
  group_by(ID) %>% 
  mutate(value = ifelse(value == lag(value, unique(RemovePrior)-1), NA, value)) %>% 
  pivot_wider(
    names_from = name,
    values_from = value
  )

输出:

     ID RemovePrior Var_1 Var_2 Var_3 Var_4 Var_5
  <dbl>       <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1     1           3    NA    NA    25    35    40
2     2           2    NA    50    45    55    60
3     3           4    NA    NA    NA    75    80
4     4           5    NA    NA    NA    NA    85