我正在尝试创建一个新的数据框,该框基于调查答案计算分数。我似乎无法正确获得分数数据框。
我尝试在for循环中使用一系列if else语句。
df <- rbind(c("Y", "no", "Often"), c("N", "yes", "always"), c("Y", "yes",
"never"))
score <- as.data.frame(matrix(0, nrow = 3, ncol = 3))
t <- 1
for (t in nrow(df)) {
if (df[t,1] == "Y") {
score[t,1] <- 2
} else if (df[t,2] == "yes") {
score[t,2] <- 2
} else if (df[t,3] == "always") {
score[t,3] <- 2
} else if (df[t,3] == "often") {
score[t,3] <- 1
}
next
}
我正在寻找输出为: 2 0 1 0、2、2 2、2、0
我得到: 0、0、0, 0、0、0, 2、0、0
答案 0 :(得分:2)
因为进入循环之前,t
被分配了等于nrow(df)
的单个值。
这是您的重做(也纠正了错字):
df <- rbind(c("Y", "no", "Often"),
c("N", "yes", "always"),
c("Y", "yes", "never"))
score <- as.data.frame(matrix(0, nrow = 3, ncol = 3))
for (t in 1:nrow(df)) {
if (df[t,1] == "Y") {
score[t,1] <- 2
}
if (df[t,2] == "yes") {
score[t,2] <- 2
}
if (df[t,3] == "always") {
score[t,3] <- 2
}
if (df[t,3] == "Often") {
score[t,3] <- 1
}
}
score
V1 V2 V3
1 2 0 1
2 0 2 2
3 2 2 0
答案 1 :(得分:1)
一种方法可能是转换为因子,设置标签,然后再返回数字。
matrix(as.numeric(as.character(
factor(as.vector(df),
levels=c("always", "N", "never", "no", "Often", "Y", "yes"),
labels=c(2, 0, 0, 0, 1, 2, 2)))), 3)
# [,1] [,2] [,3]
# [1,] 2 0 1
# [2,] 0 2 2
# [3,] 2 2 0
注意:如果df
是数据帧,而不是示例中的矩阵,则必须使用as.vector(as.matrix(df))
。
答案 2 :(得分:0)
以下是使用if
或else
绕过循环和dplyr::case_when
/ dplyr::recode
结构的几种方法。这两个功能都提供了进行此替换的矢量化方法。这里的所有选项都将获得相同的输出。
dplyr::recode
采用一组键值对,并带有可选的默认值。它还可以使用一个命名列表,用!!!
取消引号,从而允许您保存查找向量。使用apply
而不是循环:
library(dplyr)
as.data.frame(apply(df, 1, function(x) {
recode(x,
Y = 2,
yes = 2,
always = 2,
Often = 1,
.default = 0)
}))
#> V1 V2 V3
#> 1 2 0 2
#> 2 0 2 2
#> 3 1 2 0
# with a lookup and !!!
lookup <- c(Y = 2, yes = 2, always = 2, Often = 1)
as.data.frame(apply(df, 1, function(x) recode(x, !!!lookup, .default = 0)))
您还可以通过重新编码,将其制成矩阵,然后将其作为数据框(类似于下面的内容)来实现这些方法。
另一个选项是dplyr::case_when
,它类似于矢量化的switch
语句。这里的一个优点是,由于您有多个被2替换的值,因此可以使用%in%
而不是重复自己。
as.data.frame(matrix(case_when(
df %in% c("Y", "yes", "always") ~ 2,
df == "Often" ~ 1,
T ~ 0
), nrow = 3, ncol = 3))
最后,dplyr::mutate_all
允许您在转换为数据帧后在所有列上使用recode
。
mutate_all(as.data.frame(df), recode, !!!lookup, .default = 0)