ifelse()函数中语句的顺序在R中重要吗?

huangapple go评论89阅读模式
英文:

Does the order of the statement in ifelse() matter in R

问题

这是我的数据集:

  1. a <- c(1, NA, 1, 1, 1, NA, NA, 1, NA, 1, 1)
  2. b <- c(NA, 1, NA, NA, 1, 1, 1, 1, 1, NA, NA)
  3. df <- data.frame(a, b)

我想要创建一个新变量,即:
当a为1,b为1时,产生"both"
当a为NA,b为1时,产生"B"
当a为1,b为NA时,产生"A"

我不明白,为什么只有最后一段代码给了我正确的结果:

  1. df$c <- ifelse(df$a == 1 & df$b == 1, "Both",
  2. ifelse(df$a == 1 & is.na(df$b), "A",
  3. ifelse(df$b == 1 & is.na(df$a), "B", NA)))
  4. df$d <- ifelse(df$a == 1 & is.na(df$b), "A",
  5. ifelse(df$a == 1 & df$b == 1, "Both",
  6. ifelse(df$b == 1 & is.na(df$a), "B", NA)))
  7. df$e <- ifelse(df$a == 1 & is.na(df$b), "A",
  8. ifelse(df$b == 1 & is.na(df$a), "B",
  9. ifelse(df$b == 1 & df$a == 1, "Both", NA)))
  10. df

希望这些代码有帮助。

英文:

This is my dataset:

  1. a &lt;- c(1, NA, 1, 1, 1, NA, NA, 1, NA, 1, 1)
  2. b &lt;- c(NA, 1, NA, NA,1, 1, 1, 1,1, NA, NA)
  3. df &lt;- 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

  1. df$c &lt;- ifelse(df$a ==1 &amp; df$b == 1, &quot;Both&quot;,
  2. ifelse(df$a == 1 &amp; is.na(df$b), &quot;A&quot;,
  3. ifelse(df$b == 1 &amp; is.na(df$a), &quot;B&quot;, NA)))
  4. df$d &lt;- ifelse(df$a ==1 &amp; is.na(df$b), &quot;A&quot;,
  5. ifelse(df$a == 1 &amp; df$b==1, &quot;Both&quot;,
  6. ifelse(df$b == 1 &amp; is.na(df$a), &quot;B&quot;, NA)))
  7. df$e &lt;- ifelse(df$a ==1 &amp; is.na(df$b), &quot;A&quot;,
  8. ifelse(df$b ==1 &amp; is.na(df$a), &quot;B&quot;,
  9. ifelse(df$b == 1 &amp; df$a == 1, &quot;Both&quot;, NA)))
  10. 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.

  1. 是的,顺序很重要。从左到右的评估将在结果已知时停止。

ifelse returns NA in case the evaluation gives NA.

  1. `ifelse` 在评估为 `NA` 时返回 `NA`

So using ifelse it could look like:

  1. 因此,使用 `ifelse` 可能如下所示:

An alternative could be to use switch.

  1. 另一种选择是使用 `switch`
英文:

Yes, the order matters. The evaluation from left to right will stop as soon as the result is known.

  1. TRUE &amp; NA
  2. #[1] NA
  3. TRUE | NA
  4. #[1] TRUE
  5. FALSE &amp; NA
  6. #[1] FALSE
  7. FALSE | NA
  8. #[1] NA

ifelse returns NA in case the evaluation gives NA.

  1. ifelse(TRUE, 1, 0)
  2. #[1] 1
  3. ifelse(FALSE, 1, 0)
  4. #[1] 0
  5. ifelse(NA, 1, 0)
  6. #[1] NA

So using ifelse it could look like:

  1. with(df, ifelse(!is.na(a) &amp; a == 1 &amp; !is.na(b) &amp; b == 1, &quot;Both&quot;,
  2. ifelse(!is.na(a) &amp; a == 1 &amp; is.na(b), &quot;A&quot;,
  3. ifelse(!is.na(b) &amp; b == 1 &amp; is.na(a), &quot;B&quot;, NA))))
  4. # [1] &quot;A&quot; &quot;B&quot; &quot;A&quot; &quot;A&quot; &quot;Both&quot; &quot;B&quot; &quot;B&quot; &quot;Both&quot; &quot;B&quot; &quot;A&quot;
  5. #[11] &quot;A&quot;

An alternative could be to use switch.

  1. sapply(paste(df$a, df$b), switch,
  2. &quot;1 1&quot; = &quot;Both&quot;,
  3. &quot;1 NA&quot; = &quot;A&quot;,
  4. &quot;NA 1&quot; = &quot;B&quot;,
  5. NA)
  6. # 1 NA NA 1 1 NA 1 NA 1 1 NA 1 NA 1 1 1 NA 1 1 NA 1 NA
  7. # &quot;A&quot; &quot;B&quot; &quot;A&quot; &quot;A&quot; &quot;Both&quot; &quot;B&quot; &quot;B&quot; &quot;Both&quot; &quot;B&quot; &quot;A&quot; &quot;A&quot;

答案2

得分: 1

Sure, here's the translated code:

由于您的 df$adf$b 中都有 NA,如果进行值比较,您将得到 NA。此外,在 ifelse 中不会评估 NA,因此它将保持为 NA

例如:

  1. df$a == 1 & df$b == 1
  2. [1] NA NA NA NA TRUE NA NA TRUE NA NA NA

使用 dplyr::case_when() 可以解决这个问题,而且代码更可读,而不是嵌套一堆 ifelse

  1. library(dplyr)
  2. df %>%
  3. mutate(
  4. c = case_when(a == 1 & b == 1 ~ "Both",
  5. a == 1 & is.na(b) ~ "A",
  6. b == 1 & is.na(a) ~ "B",
  7. TRUE ~ NA_character_)
  8. )

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:

  1. df$a == 1 &amp; df$b == 1
  2. [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.

  1. library(dplyr)
  2. df |&gt; mutate(
  3. c = case_when(a == 1 &amp; b == 1 ~ &quot;Both&quot;,
  4. a == 1 &amp; is.na(b) ~ &quot;A&quot;,
  5. b == 1 &amp; is.na(a) ~ &quot;B&quot;,
  6. TRUE ~ NA_character_)
  7. )
  8. a b c
  9. 1 1 NA A
  10. 2 NA 1 B
  11. 3 1 NA A
  12. 4 1 NA A
  13. 5 1 1 Both
  14. 6 NA 1 B
  15. 7 NA 1 B
  16. 8 1 1 Both
  17. 9 NA 1 B
  18. 10 1 NA A
  19. 11 1 NA A

huangapple
  • 本文由 发表于 2023年4月11日 11:40:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/75982230.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定