我有一个包含大量变量的数据框。这些变量的子集名称中包含一个数字(例如x1_v
和x2_v
),我想为任意大小的子集重新编码这些变量的值。我使用for循环尝试了以下操作,但它没有重新编码。
library(car)
library(magrittr)
# Sample df
x1_v <- seq(1:5)
x2_v <- rep(5,5)
fun <- c("a","b","c","r","q")
data <- data.frame(x1_v, x2_v, fun)
# Loop
for (i in 1:2){
paste0("data$x", i, "_v") %>%
assign(paste0("data$x", i, "_v") %>%
recode("c(0, 5) = NA"))
}
我知道这通过使用循环和assign()
违反了几乎所有R协议,但我试图理解
我认为制作一个列表是有道理的,但我想在最后将所有数据保存在数据框类中。
答案 0 :(得分:0)
这是不起作用的一点:
assign(paste0("data$x", i, "_v") %>%
recode("c(0, 5) = NA")
您正在传递recode
字符串,用于&#34;数据$ x1_v&#34;当var
需要向量变量时。如果你想进入组合字符串以形成表达式和函数调用的领域,你应该看看eval()
,但我认为这样做对你正在尝试做的事情有些过分。避免这种编程风格的另一个原因是它不能很好地与%>%
一起使用。
如果我正确阅读了您的代码,您正在尝试重新编码数据框中与名称中的某个模式匹配的列。您已经要求提供矢量化解决方案,dplyr
具有可以提供帮助的设施。 dplyr::mutate_at()
将是不错的选择。有一个dplyr::recode()
,但它需要您详尽地指定所有案例,并且对类型非常挑剔。例如,这是我用dplyr::recode()
来捕捉你的意图的最接近的地方:
library(dplyr)
data %>%
mutate_at( .funs = funs(recode(., `0` = NA_real_,
`5` = NA_real_,
`1` = 1,
`2` = 2,
`3` = 3,
`4` = 4)),
.cols = vars(matches("x[0-9].*_v"))
)
请注意使用正在对列名进行正则表达式匹配的.cols = vars(matches("x[0-9].*_v")
来查找x#_v
个。此外,在funs()
内.
指的是我正在操作的列。&#39;不是&#39;管道传递的输出。&#39;
也许ifelse()
或if_else()
是更好的选择。 ifelse()
(速度较慢,类型较安全):
data %>%
mutate_at( .funs = funs(ifelse(. == 0| . == 5,
yes = NA,
no = .)),
.cols = vars(matches("x[0-9].*_v"))
)
if_else()
需要x2_v
和x1_v
的类型相同,而目前它们并不相同。 x2_v <- rep(as.integer(5),5)
会解决这个问题。然后你可以这样做:
data %>%
mutate_at( .funs = funs(if_else(. == 0| . == 5,
true = NA_integer_,
false = .)),
.cols = vars(matches("x[0-9].*_v"))
)