在数据帧上循环行并应用if-else

时间:2017-11-19 05:10:02

标签: r

我有一个名为“final”的数据框,有五列,如下所示:

quest  opt1  opt2  opt3 opt4   answer
asdsf    as   pe    dsf  qqqq    A
asdsf    sa   pe    dsf  qqqq    B
asdsf    ee   pe    dsf  qqqq    C
.
.
.
2000 rows

我想要的是

final$answer[1] has A then final$answer[1] <- final$opt1[1]
if final$answer[1] has B then final$answer[1] <- final$opt2[1] 
final$answer[1] has C then final$answer[1] <- final$opt3[1]
final$answer[1] has D then final$answer[1] <- final$opt4[1]

......对于数据帧的所有行都是如此。

所以我在下面写了循环和if-else,尽管它有效。 如果可以,请建议更好的选择?

for (i in 1:nrow(final)){

  if (final$answer[i] == "A"){

   final$answer[i] <- final$opt1[i];
                           }
else if (final$answer[i] == "B"){
final$answer[i] <- final$opt2[i];

}
else if(final$answer[i] == "C"){
final$answer[i] <- final$opt3[i];

}
else{
final$answer[i] <- final$opt4[i];
}
    }

3 个答案:

答案 0 :(得分:4)

您可以使用ifelse()功能。第一个参数是逻辑条件,第二个参数是值,如果为true,第三个参数是false,如果为false。

例如我想你想要:

final$answer <- ifelse(final$answer == "A", final$opt1, 
                  ifelse(final$answer == "B", final$opt2,
                  ifelse(final$answer == "C", final$opt3, final$opt4)))

此外,由于R使用矢量化函数,因此无需遍历每一行。

答案 1 :(得分:4)

要避免长嵌套ifelse块,您还可以使用dplyr::case_whencase_when中的每一行都按顺序进行评估,最后一个条件TRUE的功能类似于else

您也可以在dplyr::mutate来电中执行此操作,以避免所有df$

library(dplyr)

df %>% 
  mutate(
    final_answer = case_when(
      answer == "A" ~ opt1,
      answer == "B" ~ opt2,
      answer == "C" ~ opt3,
      TRUE          ~ opt4
    )
  )

#> # A tibble: 3 x 7
#>   quest  opt1  opt2  opt3  opt4 answer final_answer
#>   <chr> <chr> <chr> <chr> <chr>  <chr>        <chr>
#> 1 asdsf    as    pe   dsf  qqqq      A           as
#> 2 asdsf    sa    pe   dsf  qqqq      B           pe
#> 3 asdsf    ee    pe   dsf  qqqq      C          dsf


# or, without mutate:

df$final_answer <- case_when(
  df$answer == "A" ~ df$opt1,
  df$answer == "B" ~ df$opt2,
  df$answer == "C" ~ df$opt3,
  TRUE             ~ df$opt4
)

加载数据:

df <- readr::read_table("quest  opt1  opt2  opt3 opt4   answer
asdsf    as   pe    dsf  qqqq    A
asdsf    sa   pe    dsf  qqqq    B
asdsf    ee   pe    dsf  qqqq    C")

答案 2 :(得分:1)

另外,为了避免嵌套ifelse,您可以使用矩阵索引。如此:

dat[c("opt1","opt2","opt3","opt4")][
  cbind(seq_len(nrow(dat)), match(dat$answer, c("A","B","C","D")))
]
#[1] "as"   "pe"   "dsf"  "qqqq"

dat的位置:

dat <- data.frame(quest = c("asdsf", "asdsf", "asdsf", "asdsf"), 
opt1 = c("as", "sa", "ee", "ff"), opt2 = c("pe", "pe", "pe", 
"pe"), opt3 = c("dsf", "dsf", "dsf", "dsf"), opt4 = c("qqqq", 
"qqqq", "qqqq", "qqqq"), answer = c("A", "B", "C", "D"))