用于将多个列重新编码为新列的 tidyverse 解决方案,其中列名后缀增加一
tidyverse solution for recoding several columnsinto new ones where column name suffixes increase by one
这只是伪代码,但假设我有 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))
在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
选项,一个opiton是在across
循环'nm2'中指定的偶数列时获取列名,然后提取后缀数字结束,转换为数字,减去 1 以创建奇数列名称,get
列的值并执行 replace
ment
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
这只是伪代码,但假设我有 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))
在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
选项,一个opiton是在across
循环'nm2'中指定的偶数列时获取列名,然后提取后缀数字结束,转换为数字,减去 1 以创建奇数列名称,get
列的值并执行 replace
ment
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