2017-11-11 162 views
1

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

所以我有这样的:

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 

我想什么实现的是:在检索(块2),如果setAorB是 “A”,那么条件老了”。我尝试了这个基本循环,但显然,只适用于旧物品,因为它不会区分诱饵与新物品。

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”和单词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 

任何人都可以使用此代码有所帮助我还在学习,我挣扎了很多?

+0

我想很容易做到你想要的,但请张贴预期的最终产出。 – PoGibas

+0

我刚刚编辑过帖子,包括预期的最终输出 – Lollo

+0

也许你需要'library(data.table); setDT(loris_data)[phase ==“Block2”,condition:= c('new','old','lure')[as.integer(factor(1 + 2 *(setAorB ==“A”)+ 4 *(setAorB ==“B”&WordID%in%loris_data $ WordID [loris_data $ setAorB ==“A”]))]]]'将列条件转换为字符或使用'condition < - rep(NA_character_,times = 14)' – akrun

回答

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"] 
+0

非常感谢。 – Lollo

+0

@LorisNaspi乐于助人:-) – PoGibas

+1

你会建议data.tables over data.frames吗? – Lollo

0

您是否尝试过ifelse方法? ifelse是R中的一个内置函数,它运行矢量化if测试并给出确定的输出。例如:

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

但是,如果您想要在no内嵌入另一个ifelse,那就太好了! 让我知道它是否有效。

+0

loris_data $ condition < - ifelse(test = loris_data [,“setAorB”] ==“A”, yes =“old”, no =“new”)此代码不区分“lure”和“新”项目,艰难。请看看我的预期产出 – Lollo

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,则conditonlure

  3. 如果phase匹配Block2setAorB比赛AWordID_count较大是1,conditonnew

  4. 如果没有上述情况,则应该是NA

最后一块的代码是select(-WordID_count),它简单地去除WordID_count列,因为它是不是原来的数据帧的一部分。

+1

非常感谢你 – Lollo