2017-10-04 243 views
2

我創建了一個數據幀數據如下我應該如何使用嵌套的ifelse語句?

name <- c("A","B","C","D","E","F","G","H","I","J") 
age <- c(22,43,12,17,29,5,51,56,9,44) 
sex <- c("M","F","M","M","M","F","F","M","F","F") 
rock <- data.frame(name,age,sex,stringsAsFactors = TRUE) 
rock 

現在我想了解一下:

如果名字是E至J和性行爲不等於到F,則狀態爲「1F 「,如果名字是A到D並且年齡大於15,那麼狀態是」年輕「。一切是「其他」

所以說,我申請以下代碼:

rock$status <- ifelse(rock$name==c("E","F","G","H","I","J")& 
rock$sex!="F","1F",    
ifelse(rock$name==c("E","F","G","H","I","J")&rock$sex=="F","Fenamle", 
ifelse(rock$name==c("A","B","C","D") & rock$age>15,"Young","Others"))) 
rock 

但我得到的輸出,如:

name age sex status 
1  A 22  M Young 
2  B 43  F Young 
3  C 12  M Others 
4  D 17  M Young 
5  E 29  M Others 
6  F 5  F Others 
7  G 51  F Others 
8  H 56  M Others 
9  I 9  F Others 
10 J 44  F Others 

但是,它必須是「1F 「在E和H上,但它顯示」其他「

我的代碼有什麼問題?

請糾正我,也給我一些關於此的寶貴建議。

+0

相關崗位:https://stackoverflow.com/questions/42637099/difference-between-the-and-in-operators -in-r – zx8754

回答

7

我們需要使用%in%而不是==

rock$status <- ifelse(rock$name %in% c("E", "F", "G", "H", "I", "J") & 
         rock$sex != "F", "1F",    
         ifelse(rock$name %in% c("E", "F", "G", "H", "I", "J") & 
           rock$sex == "F", "Female", 
          ifelse(rock$name %in% c("A", "B", "C", "D") & 
             rock$age > 15, "Young", "Others"))) 
rock 

# name age sex status 
# 1  A 22 M Young 
# 2  B 43 F Young 
# 3  C 12 M Others 
# 4  D 17 M Young 
# 5  E 29 M  1F 
# 6  F 5 F Female 
# 7  G 51 F Female 
# 8  H 56 M  1F 
# 9  I 9 F Female 
# 10 J 44 F Female 
2

隨着data.table你可以這樣做:

library(data.table) 
rock <- data.table(rock) 
rock[name %in% LETTERS[5:10] & sex != "F", status := "1F"] 
rock[name %in% LETTERS[1:4] & age > 15, status := "Young"] 
rock[is.na(status), status := "Other"] 
rock 
#  name age sex status 
# 1: A 22 M Young 
# 2: B 43 F Young 
# 3: C 12 M Other 
# 4: D 17 M Young 
# 5: E 29 M  1F 
# 6: F 5 F Other 
# 7: G 51 F Other 
# 8: H 56 M  1F 
# 9: I 9 F Other 
# 10: J 44 F Other 
+1

你錯過了一個條件,也許包括這個? – Jaap

+0

該條款未在文中提及,但僅在代碼中提及。這就是爲什麼我沒有包括它。 – guscht

5

在這樣的情況下,我往往更喜歡預分配索引,然後索引這些獨特的價值總結。它比嵌套的ifelse(imo)更快,更具可讀性。一個例子:

i1 <- rock$name %in% c("E", "F", "G", "H", "I", "J") & rock$sex != "F" 
i2 <- rock$name %in% c("E", "F", "G", "H", "I", "J") & rock$sex == "F" 
i3 <- rock$name %in% c("A", "B", "C", "D") & rock$age > 15 

rock$status <- c("Other", "1F", "Female", "Young")[1 + i1 + 2*i2 + 3*i3] 

其給出所期望的結果:

> rock 
    name age sex status 
1  A 22 M Young 
2  B 43 F Young 
3  C 12 M Other 
4  D 17 M Young 
5  E 29 M  1F 
6  F 5 F Female 
7  G 51 F Female 
8  H 56 M  1F 
9  I 9 F Female 
10 J 44 F Female 
2

使用dplyrcase_when()函數A液:

library(dplyr) 

name <- c("A","B","C","D","E","F","G","H","I","J") 
age <- c(22,43,12,17,29,5,51,56,9,44) 
sex <- c("M","F","M","M","M","F","F","M","F","F") 
rock <- data.frame(name,age,sex,stringsAsFactors = TRUE) 

name_condition_1 <- c("E","F","G","H","I","J") 
name_condition_2 <- c("A","B","C","D") 

rock %>% mutate(
    status = case_when(
    name %in% name_condition_1 & sex != "F" ~ "1F", 
    name %in% name_condition_1 & sex == "F" ~ "Female", 
    name %in% name_condition_2 & age > 15 ~ "Young", 
    TRUE ~ "Others" 
) 
) 

生產:

name age sex status 
1  A 22 M Young 
2  B 43 F Young 
3  C 12 M Others 
4  D 17 M Young 
5  E 29 M  1F 
6  F 5 F Female 
7  G 51 F Female 
8  H 56 M  1F 
9  I 9 F Female 
10 J 44 F Female 
2

爲了完整起見,這裏也使用加入非等距聯接更新status列的解決方案:

library(data.table) 
setDT(rock)[.(name = LETTERS[1:4], age = 15), on = .(name, age > age), status := "Young"][ 
    .(name = LETTERS[5:10], sex = "F"), on = .(name, sex), status := "Female"][ 
    .(name = LETTERS[5:10], status = NA_character_), on = .(name, status), status := "1F"][ 
     .(status = NA_character_), on = .(status), status := "Other"][] 
name age sex status 
1: A 22 M Young 
2: B 43 F Young 
3: C 12 M Other 
4: D 17 M Young 
5: E 29 M  1F 
6: F 5 F Female 
7: G 51 F Female 
8: H 56 M  1F 
9: I 9 F Female 
10: J 44 F Female 

不幸,非平等聯盟不適用於不平等的運營商!=。所以,

setDT(rock)[.(name = LETTERS[1:4], age = 15), on = .(name, age > age), status := "Young"][ 
    .(name = LETTERS[5:10], sex = "F"), on = .(name, sex != sex), status := "1F"][] 

給出了一條錯誤消息。相反,我必須加入namesex首先將status設置爲Female,然後在status中檢查NA s以獲得免費套餐。

然而,使用兩個非等距另一個解決辦法,而不是聯接:

setDT(rock)[.(name = LETTERS[1:4], age = 15), on = .(name, age > age), status := "Young"][ 
    .(name = LETTERS[5:10], sex = "F"), on = .(name, sex < sex), status := "1F"][ 
    .(name = LETTERS[5:10], sex = "F"), on = .(name, sex > sex), status := "1F"][]