我应该如何使用嵌套的ifelse语句?
问题描述:
我创建了一个数据帧数据如下我应该如何使用嵌套的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上,但它显示”其他“
我的代码有什么问题?
请纠正我,也给我一些关于此的宝贵建议。
答
我们需要使用%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
答
随着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
答
在这样的情况下,我往往更喜欢预分配索引,然后索引这些独特的价值总结。它比嵌套的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
答
使用dplyr
的case_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
答
为了完整起见,这里也使用加入和非等距联接更新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"][]
给出了一条错误消息。相反,我必须加入name
和sex
首先将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"][]
相关岗位:https://stackoverflow.com/questions/42637099/difference-between-the-and-in-operators -in-r – zx8754