2017-10-04 257 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"][]