首页 > 解决方案 > tidyverse 解决方案,用于将多个列重新编码为列名后缀增加一的新列

问题描述

这只是伪代码,但假设我有 22 个列,从 Q46x47_1 到 Q46x47_22。

我现在想应用以下重新编码逻辑:

if Q46x47_1=0 Q46x47_2=0. 
if Q46x47_3=0 Q46x47_4=0. 
if Q46x47_5=0 Q46x47_6=0. 
if Q46x47_7=0 Q46x47_8=0. 
if Q46x47_9=0 Q46x47_10=0. 
if Q46x47_11=0 Q46x47_12=0. 
if Q46x47_13=0 Q46x47_14=0. 
if Q46x47_15=0 Q46x47_16=0. 
if Q46x47_17=0 Q46x47_18=0. 
if Q46x47_19=0 Q46x47_20=0. 
if Q46x47_21=0 Q46x47_22=0.

当然,我不想手动输入。所以我想知道是否有一种优雅的方式来批量重新编码。我知道across,但我没有看到如何通过增加的后缀号传递每个第二个变量的方法。

所以我开始:

df %>%
  mutate(across(num_range(prefix = "Q46x47_", range = seq(1, 21, 2)), ~if_else(. == 0, ..., .)))

我的问题是(假设 if_else 可以在这里使用)如何...在 if_else 命令中指定我需要传递 LHS 列名的部分。

有任何想法吗?


具有列子集的简短可重复示例:

df <- data.frame(Q46x47_1 = c(1, 2, 0, 1, 0),
                 Q46x47_2 = c(1, 2, 3, 1, 0),
                 Q46x47_3 = c(1, 2, 0, 1, 0),
                 Q46x47_4 = c(1, 2, 3, 1, 0),
                 Q46x47_5 = c(1, 2, 0, 1, 0),
                 Q46x47_6 = c(1, 2, 3, 1, 0))

标签: rtidyverserecodeacross

解决方案


base R,这更容易

nm1 <- paste0("Q46x47_", seq(1, 21, by = 2))
nm2 <- paste0("Q46x47_", seq(2, 22, by = 2))
i1 <- df[nm1] == 0
df[nm2][i1] <- 0

对于提供的示例

nm1 <- paste0("Q46x47_", seq(1, 5, by = 2))
nm2 <- paste0("Q46x47_", seq(2, 6, by = 2))

如果我们需要一个dplyr选项,一个选项是当我们循环'nm2'中指定的偶数列时获取列名across,然后提取末尾的后缀数字,转换为数字,减去1创建奇数列名,get值列的和做replace

library(dplyr)
library(stringr)
df %>%
   mutate(across(all_of(nm2), ~
                {
             tmp <- cur_column()
             replace(., get(str_c('Q46x47_', 
            as.integer(str_extract(tmp, "\\d+$"))-1)) == 0, 0)

           }))

-输出

# Q46x47_1 Q46x47_2 Q46x47_3 Q46x47_4 Q46x47_5 Q46x47_6
#1        1        1        1        1        1        1
#2        2        2        2        2        2        2
#3        0        0        0        0        0        0
#4        1        1        1        1        1        1
#5        0        0        0        0        0        0

推荐阅读