使用 R 在数据框中重新编码多个变量的最短和最干净的方法是什么?
What is the shortest and cleanest way to recode multiple variables in a dataframe using R?
所以我在社会科学领域工作,我经常要做的是操纵多个变量来改变值。这通常意味着扭转规模。我已经使用 SPSS 很长时间了,那里的语法非常简单。要更改您编写的多个变量的值:
RECODE var1 var2 var3 (1=5) (2=4) 4=2) (5=1) (ELSE=COPY).
要在新变量中编写新代码,请在末尾添加 into newvar1 newvar1 newvar3.
。在括号中,您可以使用 hi
、lo
、1 to 4
等内容。
现在我正在努力进入 R,我正在努力寻找执行类似工作流程的最佳方法。我找到了以下解决方案,但找不到简短的好方法:
## Packages -----
library(dplyr)
library(car)
## Data -----
tib <- tibble(v1 = 1:4,
v2 = 1:4,
v3 = sample(1:5, 4, replace = FALSE))
vars <- c("v1", "v2", "v3")
基本方式:
tib$v2_rec <- NA
tib$v2_rec[tib$v2 == 1] <- 5 #1
tib$v2_rec[tib$v2 == 2] <- 4 #2
tib$v2_rec[tib$v2 == 3] <- 3 #3
tib$v2_rec[tib$v2 == 4] <- 2 #4
tib$v2_rec[tib$v2 == 5] <- 1 #5
# I'm forced to create a new variable here, otherwise #4 and #5 overwrite #1 and #2.
# Therefore I won't even bother to try to loop trough multiple variables.
从包车重新编码():
tib$v1 <- recode(tib$v1, "1=5; 2=4; 4=2; 5=1")
# This is nice, understandable and short
# To handle multiple variables the following solutions won't work, because the reload functions seems not to be able to iterate through lists:
tib[vars] <- recode(tib[vars], "1=5; 2=4; 4=2; 5=1")
tib[1:3] <- recode(tib[1:3], "1=5; 2=4; 4=2; 5=1")
# I'd be forced to loop:
for (i in vars) {
tib[[i]] <- recode(tib[[i]], "1=5; 2=4; 4=2; 5=1")
}
我对此非常满意,但我想知道是否有一个函数可以为我完成循环工作。我现在真的在为 dplyer 函数苦苦挣扎,我很不高兴我无法直观地解决问题...
我试过变异:
#I get it for a single case and for multiple cases i got to a solution in combination with the recode() function:
tib <- tib %>%
mutate_at(vars(v1:v3),
function(x) recode(x, "1=5; 2=4; 4=2; 5=1"))
这是最好的方法吗?需要说明的是,我看到了一些其他使用 case_when()、replace() 或 mapvalues() 的解决方案,但我发现上面的解决方案更好,因为我喜欢一眼就看到什么值被重新编码为什么值。
我对 apply() 函数有了一点了解,甚至无法用它重新编码一个变量。我相信我很快就会掌握这一点,但目前我只是有点沮丧,因为我在 SPSS 中花了我一行的时间来寻找工作流程。如果您知道比上述使用 apply() 函数的解决方案更短更清晰的解决方案,我将不胜感激!
我对 R 及其可能性感到满意,但现在我需要正确方向的提示来让我继续前进!提前致谢!
这是一种仅使用基本函数的简单方法。这假设这些是原始编码为 1 - 5 的 5 点李克特项目。如果你有,比如说,7 点李克特项目,或者编码为 0 - 4,或 -2 - 2,你需要调整这个.
一些编码说明:您的数据集有一个伪随机生成元素(对 sample()
的调用);要使数据集完全可重现,请使用 ?set.seed。在使用箭头赋值运算符 ((var <- value)
) 时,您可以自动打印已赋值的变量或数据集,方法是将其括在括号中。 R 是矢量化的,因此您不需要循环(尽管这里真的没问题——变量很少,不会导致明显的减速)。
set.seed(4636) # this makes the example exactly reproducible
(d <- data.frame(v1 = 1:4,
v2 = 1:4,
v3 = sample(1:5, 4, replace = FALSE))) # adding outer ()'s prints
# v1 v2 v3
# 1 1 1 1
# 2 2 2 2
# 3 3 3 5
# 4 4 4 4
d.orig <- d # here's your original dataset, so they aren't overwritten
(d <- 6-d) # adding outer ()'s prints
# v1 v2 v3
# 1 5 5 5
# 2 4 4 4
# 3 3 3 1
# 4 2 2 2
rec.vars <- c("v2")
d.some <- d.orig
(d.some[,rec.vars] <- 6-d.some[,rec.vars])
# [1] 5 4 3 2
d.some
# v1 v2 v3
# 1 1 5 1
# 2 2 4 2
# 3 3 3 5
# 4 4 2 4
##### to do more than 1 variable
(rec.vars <- paste0("v", c(2,3)))
# [1] "v2" "v3"
d.some <- d.orig
(d.some[,rec.vars] <- 6-d.some[,rec.vars])
# v2 v3
# 1 5 5
# 2 4 4
# 3 3 1
# 4 2 2
d.some
# v1 v2 v3
# 1 1 5 5
# 2 2 4 4
# 3 3 3 1
# 4 4 2 2
我认为如果使用正确,dplyr
在这种情况下具有 "cleanest" 语法:
library(dplyr)
tib <- tibble(v1 = 1:4,
v2 = 1:4,
v3 = sample(1:5, 4, replace = FALSE))
tib %>%
mutate_at(vars(v1:v3), recode, `1` = 5, `2` = 4, `3` = 3, `4` = 2, `5` = 1)
#> # A tibble: 4 x 3
#> v1 v2 v3
#> <dbl> <dbl> <dbl>
#> 1 5 5 2
#> 2 4 4 5
#> 3 3 3 4
#> 4 2 2 1
请注意,我必须添加 3 = 3
,因为重新编码需要替换所有值。
我经常发现用对我来说新的函数更明确地写东西更容易,所以这可能会有所帮助:
tib %>%
mutate_at(.vars = vars(v1:v3),
.funs = function(x) recode(x,
`1` = 5,
`2` = 4,
`3` = 3,
`4` = 2,
`5` = 1))
如果您更喜欢 car
中的 recode
函数,则不应加载 car
,而应使用:
tib %>%
mutate_at(vars(v1:v3), car::recode, "1=5; 2=4; 4=2; 5=1")
这样你就不会 运行 将 dplyr
与 car
混合使用(只要你不需要 car
做其他事情。
所以我在社会科学领域工作,我经常要做的是操纵多个变量来改变值。这通常意味着扭转规模。我已经使用 SPSS 很长时间了,那里的语法非常简单。要更改您编写的多个变量的值:
RECODE var1 var2 var3 (1=5) (2=4) 4=2) (5=1) (ELSE=COPY).
要在新变量中编写新代码,请在末尾添加 into newvar1 newvar1 newvar3.
。在括号中,您可以使用 hi
、lo
、1 to 4
等内容。
现在我正在努力进入 R,我正在努力寻找执行类似工作流程的最佳方法。我找到了以下解决方案,但找不到简短的好方法:
## Packages -----
library(dplyr)
library(car)
## Data -----
tib <- tibble(v1 = 1:4,
v2 = 1:4,
v3 = sample(1:5, 4, replace = FALSE))
vars <- c("v1", "v2", "v3")
基本方式:
tib$v2_rec <- NA
tib$v2_rec[tib$v2 == 1] <- 5 #1
tib$v2_rec[tib$v2 == 2] <- 4 #2
tib$v2_rec[tib$v2 == 3] <- 3 #3
tib$v2_rec[tib$v2 == 4] <- 2 #4
tib$v2_rec[tib$v2 == 5] <- 1 #5
# I'm forced to create a new variable here, otherwise #4 and #5 overwrite #1 and #2.
# Therefore I won't even bother to try to loop trough multiple variables.
从包车重新编码():
tib$v1 <- recode(tib$v1, "1=5; 2=4; 4=2; 5=1")
# This is nice, understandable and short
# To handle multiple variables the following solutions won't work, because the reload functions seems not to be able to iterate through lists:
tib[vars] <- recode(tib[vars], "1=5; 2=4; 4=2; 5=1")
tib[1:3] <- recode(tib[1:3], "1=5; 2=4; 4=2; 5=1")
# I'd be forced to loop:
for (i in vars) {
tib[[i]] <- recode(tib[[i]], "1=5; 2=4; 4=2; 5=1")
}
我对此非常满意,但我想知道是否有一个函数可以为我完成循环工作。我现在真的在为 dplyer 函数苦苦挣扎,我很不高兴我无法直观地解决问题...
我试过变异:
#I get it for a single case and for multiple cases i got to a solution in combination with the recode() function:
tib <- tib %>%
mutate_at(vars(v1:v3),
function(x) recode(x, "1=5; 2=4; 4=2; 5=1"))
这是最好的方法吗?需要说明的是,我看到了一些其他使用 case_when()、replace() 或 mapvalues() 的解决方案,但我发现上面的解决方案更好,因为我喜欢一眼就看到什么值被重新编码为什么值。
我对 apply() 函数有了一点了解,甚至无法用它重新编码一个变量。我相信我很快就会掌握这一点,但目前我只是有点沮丧,因为我在 SPSS 中花了我一行的时间来寻找工作流程。如果您知道比上述使用 apply() 函数的解决方案更短更清晰的解决方案,我将不胜感激!
我对 R 及其可能性感到满意,但现在我需要正确方向的提示来让我继续前进!提前致谢!
这是一种仅使用基本函数的简单方法。这假设这些是原始编码为 1 - 5 的 5 点李克特项目。如果你有,比如说,7 点李克特项目,或者编码为 0 - 4,或 -2 - 2,你需要调整这个.
一些编码说明:您的数据集有一个伪随机生成元素(对 sample()
的调用);要使数据集完全可重现,请使用 ?set.seed。在使用箭头赋值运算符 ((var <- value)
) 时,您可以自动打印已赋值的变量或数据集,方法是将其括在括号中。 R 是矢量化的,因此您不需要循环(尽管这里真的没问题——变量很少,不会导致明显的减速)。
set.seed(4636) # this makes the example exactly reproducible
(d <- data.frame(v1 = 1:4,
v2 = 1:4,
v3 = sample(1:5, 4, replace = FALSE))) # adding outer ()'s prints
# v1 v2 v3
# 1 1 1 1
# 2 2 2 2
# 3 3 3 5
# 4 4 4 4
d.orig <- d # here's your original dataset, so they aren't overwritten
(d <- 6-d) # adding outer ()'s prints
# v1 v2 v3
# 1 5 5 5
# 2 4 4 4
# 3 3 3 1
# 4 2 2 2
rec.vars <- c("v2")
d.some <- d.orig
(d.some[,rec.vars] <- 6-d.some[,rec.vars])
# [1] 5 4 3 2
d.some
# v1 v2 v3
# 1 1 5 1
# 2 2 4 2
# 3 3 3 5
# 4 4 2 4
##### to do more than 1 variable
(rec.vars <- paste0("v", c(2,3)))
# [1] "v2" "v3"
d.some <- d.orig
(d.some[,rec.vars] <- 6-d.some[,rec.vars])
# v2 v3
# 1 5 5
# 2 4 4
# 3 3 1
# 4 2 2
d.some
# v1 v2 v3
# 1 1 5 5
# 2 2 4 4
# 3 3 3 1
# 4 4 2 2
我认为如果使用正确,dplyr
在这种情况下具有 "cleanest" 语法:
library(dplyr)
tib <- tibble(v1 = 1:4,
v2 = 1:4,
v3 = sample(1:5, 4, replace = FALSE))
tib %>%
mutate_at(vars(v1:v3), recode, `1` = 5, `2` = 4, `3` = 3, `4` = 2, `5` = 1)
#> # A tibble: 4 x 3
#> v1 v2 v3
#> <dbl> <dbl> <dbl>
#> 1 5 5 2
#> 2 4 4 5
#> 3 3 3 4
#> 4 2 2 1
请注意,我必须添加 3 = 3
,因为重新编码需要替换所有值。
我经常发现用对我来说新的函数更明确地写东西更容易,所以这可能会有所帮助:
tib %>%
mutate_at(.vars = vars(v1:v3),
.funs = function(x) recode(x,
`1` = 5,
`2` = 4,
`3` = 3,
`4` = 2,
`5` = 1))
如果您更喜欢 car
中的 recode
函数,则不应加载 car
,而应使用:
tib %>%
mutate_at(vars(v1:v3), car::recode, "1=5; 2=4; 4=2; 5=1")
这样你就不会 运行 将 dplyr
与 car
混合使用(只要你不需要 car
做其他事情。