[英]For loop across multiple columns
我有一些问卷数据,用于衡量进入商店的频率(“_freq”)和体验的享受(“_enj”)。 总共有 17 家商店(shop1、shop2、...)和 120 行数据。 下面是仅商店 1 和 2 的 5 行数据的示例。
shop1_freq | shop1_enj | shop2_freq | shop2_enj |
---|---|---|---|
0 | 9 | 5 | 4 |
3 | 2 | 0 | 9 |
0 | 9 | 5 | 4 |
0 | 2 | 0 | 9 |
4 | 9 | 5 | 4 |
我编写了一个 for 循环,它将对问卷的错误回答标记为“999”,以便我可以识别它们。 基本上,对于每个孤立的商店,如果频率为 0 并且享受不是9,则响应不正确,或者如果频率不是0 但享受为 9,则响应不正确。目前我正在重复 17 次以下的循环(个人为每个商店,下面只是商店1)。
for (rows in 1:120){
if(data$shop1_freq[rows] == "0" & data$shop1_enj[rows] != 9) {
data$shop1_enj[rows] = "999" # label incorrect 999
}
}
for (rows in 1:120){
if(data$shop1_freq[rows] != "0" & data$shop1_enj[rows] == 9) {
data$shop1_enj[rows] = "999" # label incorrect 999
}
}
但是我想知道是否有一种更有效的方法可以用更少的代码为所有 17 家商店做到这一点?
对于多个 'shop_\d+_enj' 列及其对应的 '_freq' 列,它可以across
mutate
中完成
library(dplyr)
data1 <- data %>%
mutate(across(matches('^shop\\d+_enj$'), ~ {
tmp <- get(str_replace(cur_column(), '_enj', '_freq'))
case_when(tmp == 0 & . != 9 ~ 999,
tmp != 0 & . == 9 ~ 999,
TRUE ~ .)
}))
细节 -
我们遍历匹配 'shop' across
列,后跟一个或多个数字,然后是列名中的_
和 'enj',通过替换列名 ( get
cur_column()
) 后缀' _enj' 和 '_freq',使用它在case_when
中使用逻辑运算符创建复合条件表达式,如果值为 TRUE,则将 ( ~
) 这些行元素分配给 999,并在最后一个TRUE ~.
. 在这里, .
是列值
在base R
中,这可以通过多种方式完成。 一种选择是根据列名的模式将数据拆分为list
lst1 <- split(data1, sub("_.*", "", names(data1))
out <- do.call(cbind, lapply(lst1, function(x) {
x[[2]] <- ifelse(x[[1]] == 0 & x[[2]] != 9, 999,
ifelse(x[[1]] != 0 & x[[2]] == 9, 999, x[[2]])))
x
}))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.