2017-11-11 569 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