在for循环内使用多个if语句,条件之间

时间:2017-11-11 13:56:54

标签: r

我是一个新的R用户,我一直在尝试执行嵌套在for循环中的if语句,以便编写新的变量。我有一个data.frame,其中一些人以前忘记编写来自E-prime的“条件”变量(3个级别的因素:旧的,新的,诱惑)。该任务有两个阶段编码/检索(块1和2),两组图像(A和B)和一个唯一的Word ID。

所以我有这个:

phase <- rep(c("Block1", "Block2"), each = 7)
condition <- rep(NA, times = 14)
setAorB <- rep(c("A", "B"), times = c(9,5)) 
WordID <- c(23,34,56,76,45,88,99,23,34,56,76,45,100,105)

loris_data <- data.frame(phase,condition,setAorB,WordID) 

给了我:

> loris_data
   phase     condition setAorB WordID
1  Block1        NA       A     23
2  Block1        NA       A     34
3  Block1        NA       A     56
4  Block1        NA       A     76
5  Block1        NA       A     45
6  Block1        NA       A     88
7  Block1        NA       A     99
8  Block2        NA       A     23
9  Block2        NA       A     34
10 Block2        NA       B     56
11 Block2        NA       B     76
12 Block2        NA       B     45
13 Block2        NA       B    100
14 Block2        NA       B    105

我想要实现的是:在检索(Block2)时,如果setAorB是“A”,则条件是“old”。我尝试过这个基本循环,但显然只适用于旧项目,因为它不会区分诱饵与新项目。

for(i in 1:length(loris_data$condition)) {
      if(loris_data$setAorB[i] == "A") {
            loris_data$condition[i] <-"old"}
      else {
            loris_data$condition[i] <- "new"
      }
    }

然后,我想说:如果setAorB是“B”并且Word ID与A相同(这意味着它是诱饵),那么条件是“诱惑”,否则如果setAorB是“B”但是它有一个独特的WordID,条件是“新”。

这将是预期的输出:

> loris_data
    phase    condition setAorB WordID
1  Block1      <NA>       A     23
2  Block1      <NA>       A     34
3  Block1      <NA>       A     56
4  Block1      <NA>       A     76
5  Block1      <NA>       A     45
6  Block1      <NA>       A     88
7  Block1      <NA>       A     99
8  Block2       old       A     23
9  Block2       old       A     34
10 Block2      lure       B     56
11 Block2      lure       B     76
12 Block2      lure       B     45
13 Block2       new       B    100
14 Block2       new       B    105

任何人都可以帮助我解决这个问题,因为我还在学习,而且我正在努力奋斗吗?

3 个答案:

答案 0 :(得分:1)

使用data.table快速而肮脏的解决方案:

library(data.table)
setDT(loris_data)
loris_data[, condition := ifelse(setAorB == "A", "old", "new")]
loris_data[phase != "Block2", condition := NA]
loris_data[phase == "Block2" & setAorB == "B" & WordID %in% loris_data[phase == "Block1", WordID], condition := "lure"]

答案 1 :(得分:0)

你尝试过ifelse方法吗? ifelse是R中的内置函数,如果测试运行矢量化并给出确定的输出。例如:

loris_data$resutl <- ifelse(test = loris_data[, "condition"] == "A",
       yes =  "old", 
       no = "new")

但是,如果你想在no中嵌入另一个ifelse,那就完全没问题了! 如果有效,请告诉我。

答案 2 :(得分:0)

使用dplyr的解决方案。 loris_data2是最终输出。

library(dplyr)

loris_data2 <- loris_data %>%
  group_by(WordID) %>%
  mutate(WordID_count = row_number()) %>%
  ungroup() %>%
  mutate(condition = case_when(
    phase %in% "Block2" & setAorB %in% "A"                        ~ "old",
    phase %in% "Block2" & setAorB %in% "B" & WordID_count > 1     ~ "lure",
    phase %in% "Block2" & setAorB %in% "B" & WordID_count == 1    ~ "new",
    TRUE                                                          ~ NA_character_
  )) %>%
  select(-WordID_count)

loris_data2
# # A tibble: 14 x 4
#     phase condition setAorB WordID
#    <fctr>     <chr>  <fctr>  <dbl>
#  1 Block1      <NA>       A     23
#  2 Block1      <NA>       A     34
#  3 Block1      <NA>       A     56
#  4 Block1      <NA>       A     76
#  5 Block1      <NA>       A     45
#  6 Block1      <NA>       A     88
#  7 Block1      <NA>       A     99
#  8 Block2       old       A     23
#  9 Block2       old       A     34
# 10 Block2      lure       B     56
# 11 Block2      lure       B     76
# 12 Block2      lure       B     45
# 13 Block2       new       B    100
# 14 Block2       new       B    105

<强>解释

我的解决方案首先创建一个名为WordID_count的新列,该列显示WordID的外观时间。此任务通过以下方式实现。

loris_data %>%
  group_by(WordID) %>%
  mutate(WordID_count = row_number()) %>%
  ungroup()

# # A tibble: 14 x 5
#     phase condition setAorB WordID WordID_count
#    <fctr>     <lgl>  <fctr>  <dbl>        <int>
#  1 Block1        NA       A     23            1
#  2 Block1        NA       A     34            1
#  3 Block1        NA       A     56            1
#  4 Block1        NA       A     76            1
#  5 Block1        NA       A     45            1
#  6 Block1        NA       A     88            1
#  7 Block1        NA       A     99            1
#  8 Block2        NA       A     23            2
#  9 Block2        NA       A     34            2
# 10 Block2        NA       B     56            2
# 11 Block2        NA       B     76            2
# 12 Block2        NA       B     45            2
# 13 Block2        NA       B    100            1
# 14 Block2        NA       B    105            1

之后,就可以填写condition列了。此任务通过以下方式实现。

mutate(condition = case_when(
    phase %in% "Block2" & setAorB %in% "A"                        ~ "old",
    phase %in% "Block2" & setAorB %in% "B" & WordID_count > 1     ~ "lure",
    phase %in% "Block2" & setAorB %in% "B" & WordID_count == 1    ~ "new",
    TRUE                                                          ~ NA_character_
  ))

mutate是创建或更新新列的功能。 case_when是多个ifelse语句的替代方案。该代码完成了以下工作:

  1. 如果phase匹配Block2setAorB匹配A,则conditonold

  2. 如果phase匹配Block2setAorB匹配AWordID_count大于1,则conditon为{{ 1}}。

  3. 如果lure匹配phaseBlock2匹配setAorBA大于1,则WordID_count为{{ 1}}。

  4. 如果没有上述情况,则条件应为conditon

  5. 代码的最后一部分是new,它只删除了NA列,因为它不是原始数据框的一部分。