为什么此for循环无法正确填充新数据帧?

时间:2019-07-10 13:09:39

标签: r loops

我正在尝试创建一个新的数据框,该框基于调查答案计算分数。我似乎无法正确获得分数数据框。

我尝试在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

3 个答案:

答案 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)

以下是使用ifelse绕过循环和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)