英文:
Does the order of the statement in ifelse() matter in R
问题
这是我的数据集:
a <- c(1, NA, 1, 1, 1, NA, NA, 1, NA, 1, 1)
b <- c(NA, 1, NA, NA, 1, 1, 1, 1, 1, NA, NA)
df <- data.frame(a, b)
我想要创建一个新变量,即:
当a为1,b为1时,产生"both"
当a为NA,b为1时,产生"B"
当a为1,b为NA时,产生"A"
我不明白,为什么只有最后一段代码给了我正确的结果:
df$c <- ifelse(df$a == 1 & df$b == 1, "Both",
ifelse(df$a == 1 & is.na(df$b), "A",
ifelse(df$b == 1 & is.na(df$a), "B", NA)))
df$d <- ifelse(df$a == 1 & is.na(df$b), "A",
ifelse(df$a == 1 & df$b == 1, "Both",
ifelse(df$b == 1 & is.na(df$a), "B", NA)))
df$e <- ifelse(df$a == 1 & is.na(df$b), "A",
ifelse(df$b == 1 & is.na(df$a), "B",
ifelse(df$b == 1 & df$a == 1, "Both", NA)))
df
希望这些代码有帮助。
英文:
This is my dataset:
a <- c(1, NA, 1, 1, 1, NA, NA, 1, NA, 1, 1)
b <- c(NA, 1, NA, NA,1, 1, 1, 1,1, NA, NA)
df <- data.frame(a,b)
I want to create a new variable,that is
when a is 1, b is 1, produce "both"
when a is NA, B is 1, produce "B"
when a is 1, b is NA, produce "A"
I don't understand, why only the last chuck of codes gave me the correct results
df$c <- ifelse(df$a ==1 & df$b == 1, "Both",
ifelse(df$a == 1 & is.na(df$b), "A",
ifelse(df$b == 1 & is.na(df$a), "B", NA)))
df$d <- ifelse(df$a ==1 & is.na(df$b), "A",
ifelse(df$a == 1 & df$b==1, "Both",
ifelse(df$b == 1 & is.na(df$a), "B", NA)))
df$e <- ifelse(df$a ==1 & is.na(df$b), "A",
ifelse(df$b ==1 & is.na(df$a), "B",
ifelse(df$b == 1 & df$a == 1, "Both", NA)))
df
a | b | c | d | e |
---|---|---|---|---|
1 | NA | NA | A | A |
NA | 1 | NA | NA | B |
1 | NA | NA | A | A |
1 | NA | NA | A | A |
1 | 1 | Both | Both | Both |
NA | 1 | NA | NA | B |
NA | 1 | NA | NA | B |
1 | 1 | Both | Both | Both |
NA | 1 | NA | NA | B |
1 | NA | NA | A | A |
1 | NA | NA | A | A |
答案1
得分: 2
Yes, the order matters. The evaluation from left to right will stop as soon as the result is known.
是的,顺序很重要。从左到右的评估将在结果已知时停止。
ifelse
returns NA
in case the evaluation gives NA
.
`ifelse` 在评估为 `NA` 时返回 `NA`。
So using ifelse
it could look like:
因此,使用 `ifelse` 可能如下所示:
An alternative could be to use switch
.
另一种选择是使用 `switch`。
英文:
Yes, the order matters. The evaluation from left to right will stop as soon as the result is known.
TRUE & NA
#[1] NA
TRUE | NA
#[1] TRUE
FALSE & NA
#[1] FALSE
FALSE | NA
#[1] NA
ifelse
returns NA
in case the evaluation gives NA
.
ifelse(TRUE, 1, 0)
#[1] 1
ifelse(FALSE, 1, 0)
#[1] 0
ifelse(NA, 1, 0)
#[1] NA
So using ifelse
it could look like:
with(df, ifelse(!is.na(a) & a == 1 & !is.na(b) & b == 1, "Both",
ifelse(!is.na(a) & a == 1 & is.na(b), "A",
ifelse(!is.na(b) & b == 1 & is.na(a), "B", NA))))
# [1] "A" "B" "A" "A" "Both" "B" "B" "Both" "B" "A"
#[11] "A"
An alternative could be to use switch
.
sapply(paste(df$a, df$b), switch,
"1 1" = "Both",
"1 NA" = "A",
"NA 1" = "B",
NA)
# 1 NA NA 1 1 NA 1 NA 1 1 NA 1 NA 1 1 1 NA 1 1 NA 1 NA
# "A" "B" "A" "A" "Both" "B" "B" "Both" "B" "A" "A"
答案2
得分: 1
Sure, here's the translated code:
由于您的 df$a
和 df$b
中都有 NA
,如果进行值比较,您将得到 NA
。此外,在 ifelse
中不会评估 NA
,因此它将保持为 NA
。
例如:
df$a == 1 & df$b == 1
[1] NA NA NA NA TRUE NA NA TRUE NA NA NA
使用 dplyr::case_when()
可以解决这个问题,而且代码更可读,而不是嵌套一堆 ifelse
。
library(dplyr)
df %>%
mutate(
c = case_when(a == 1 & b == 1 ~ "Both",
a == 1 & is.na(b) ~ "A",
b == 1 & is.na(a) ~ "B",
TRUE ~ NA_character_)
)
a b c
1 1 NA A
2 NA 1 B
3 1 NA A
4 1 NA A
5 1 1 Both
6 NA 1 B
7 NA 1 B
8 1 1 Both
9 NA 1 B
10 1 NA A
11 1 NA A
英文:
Since you have NA
in your df$a
and df$b
, you would get NA
if you do value comparison. Moreover, NA
is not evaluated in your ifelse
and would therefore stays NA
.
For example:
df$a == 1 & df$b == 1
[1] NA NA NA NA TRUE NA NA TRUE NA NA NA
Using dplyr::case_when()
would solve the problem and the code is more readable without nesting a bunch of ifelse
.
library(dplyr)
df |> mutate(
c = case_when(a == 1 & b == 1 ~ "Both",
a == 1 & is.na(b) ~ "A",
b == 1 & is.na(a) ~ "B",
TRUE ~ NA_character_)
)
a b c
1 1 NA A
2 NA 1 B
3 1 NA A
4 1 NA A
5 1 1 Both
6 NA 1 B
7 NA 1 B
8 1 1 Both
9 NA 1 B
10 1 NA A
11 1 NA A
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论