在循环中跨列替换多个值

Replace multiple values across columns in a loop

我想跨不同列重新编码多个值。

例如:

df <- data.frame(wave = c(1,1,1,1,1,1,2,2,2,2,2,2),
                 party = rep(c("A", "A", "A", "B", "B", "B"), 2),
                 s_item = rep(c(3,4,5,1,2,6), 2), 
                 s_item2 = rep(c(1,2,3,4,5,6), 2),
                 s_item3 = rep(c(6,2,3,1,5,4), 2)) 

数据:

   wave party s_item s_item2 s_item3
1     1     A      3       1       6
2     1     A      4       2       2
3     1     A      5       3       3
4     1     B      1       4       1
5     1     B      2       5       5
6     1     B      6       6       4
7     2     A      3       1       6
8     2     A      4       2       2
9     2     A      5       3       3
10    2     B      1       4       1
11    2     B      2       5       5
12    2     B      6       6       4

对于所有“s_”列,我想将值“1、2、3、4、5、6”重新编码为“-1、-0.5、0、0.5、1、NA”。

那么,我需要的是:

   wave party s_item s_item2 s_item3
1     1     A    0.0    -1.0      NA
2     1     A    0.5    -0.5    -0.5
3     1     A    1.0     0.0     0.0
4     1     B   -1.0     0.5    -1.0
5     1     B   -0.5     1.0     1.0
6     1     B     NA      NA     0.5
7     2     A    0.0    -1.0      NA
8     2     A    0.5    -0.5    -0.5
9     2     A    1.0     0.0     0.0
10    2     B   -1.0     0.5    -1.0
11    2     B   -0.5     1.0     1.0
12    2     B     NA      NA     0.5

这适用于单个值:

for(i in df %>% select(starts_with("s_")) %>% colnames()){
  df[[i]] <-  replace(df[[i]], df[[i]] %in% 1, -1)
}

但这不起作用:

for(i in df %>% select(starts_with("s_")) %>% colnames()){
  df[[i]] <-  replace(df[[i]], df[[i]] %in% 1, -1,
                      df[[i]], df[[i]] %in% 2, -0.5,
                      df[[i]], df[[i]] %in% 3, 0,
                      df[[i]], df[[i]] %in% 4, 0.5,
                      df[[i]], df[[i]] %in% 5, 1,
                      df[[i]], df[[i]] %in% 6, NA,)
}

有没有办法像我在上面的代码中想象的那样在一个循环中完成此操作?只要代码尽可能紧凑,我也愿意接受不同的策略。

您可以试试下面的代码

v <- c(-1, -0.5, 0, 0.5, 1, NA)
idx <- startsWith(names(df), "s_")
df[idx] <- v[as.matrix(df[idx])]

这给出了

> df
   wave party s_item s_item2 s_item3
1     1     A    0.0    -1.0      NA
2     1     A    0.5    -0.5    -0.5
3     1     A    1.0     0.0     0.0
4     1     B   -1.0     0.5    -1.0
5     1     B   -0.5     1.0     1.0
6     1     B     NA      NA     0.5
7     2     A    0.0    -1.0      NA
8     2     A    0.5    -0.5    -0.5
9     2     A    1.0     0.0     0.0
10    2     B   -1.0     0.5    -1.0
11    2     B   -0.5     1.0     1.0
12    2     B     NA      NA     0.5

使用 acrossrecode -

library(dplyr)

df <- df %>%
  mutate(across(starts_with('s_'), 
        ~recode(., `1` = -1, `2` = -0.5, `3` = 0, 
                    `4` = 0.5, `5` = 1, `6` = NA_real_)))
df


#   wave party s_item s_item2 s_item3
#1     1     A    0.0    -1.0      NA
#2     1     A    0.5    -0.5    -0.5
#3     1     A    1.0     0.0     0.0
#4     1     B   -1.0     0.5    -1.0
#5     1     B   -0.5     1.0     1.0
#6     1     B     NA      NA     0.5
#7     2     A    0.0    -1.0      NA
#8     2     A    0.5    -0.5    -0.5
#9     2     A    1.0     0.0     0.0
#10    2     B   -1.0     0.5    -1.0
#11    2     B   -0.5     1.0     1.0
#12    2     B     NA      NA     0.5

使用命名向量

library(dplyr)
df %>%
    mutate(across(starts_with("s_"), 
   ~ setNames(c(-1, -0.5, 0, 0.5, 1, NA), 1:6)[as.character(.)]))
   wave party s_item s_item2 s_item3
1     1     A    0.0    -1.0      NA
2     1     A    0.5    -0.5    -0.5
3     1     A    1.0     0.0     0.0
4     1     B   -1.0     0.5    -1.0
5     1     B   -0.5     1.0     1.0
6     1     B     NA      NA     0.5
7     2     A    0.0    -1.0      NA
8     2     A    0.5    -0.5    -0.5
9     2     A    1.0     0.0     0.0
10    2     B   -1.0     0.5    -1.0
11    2     B   -0.5     1.0     1.0
12    2     B     NA      NA     0.5