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

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

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 &lt;- c(1, NA, 1, 1, 1, NA, NA, 1, NA, 1, 1)
b &lt;- c(NA, 1, NA, NA,1, 1, 1,   1,1, NA, NA)
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

df$c &lt;- ifelse(df$a ==1 &amp; df$b == 1, &quot;Both&quot;,
               ifelse(df$a == 1 &amp; is.na(df$b), &quot;A&quot;,
                      ifelse(df$b == 1 &amp; is.na(df$a), &quot;B&quot;, NA)))


df$d &lt;- ifelse(df$a ==1 &amp; is.na(df$b), &quot;A&quot;,
               ifelse(df$a == 1 &amp; df$b==1, &quot;Both&quot;,
                      ifelse(df$b == 1 &amp; is.na(df$a), &quot;B&quot;, NA)))



df$e &lt;- ifelse(df$a ==1 &amp; is.na(df$b), &quot;A&quot;,
               ifelse(df$b ==1 &amp; is.na(df$a), &quot;B&quot;,
                      ifelse(df$b == 1 &amp; df$a == 1, &quot;Both&quot;, 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 &amp; NA
#[1] NA

TRUE | NA
#[1] TRUE

FALSE &amp; 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) &amp; a == 1 &amp; !is.na(b) &amp; b == 1, &quot;Both&quot;,
         ifelse(!is.na(a) &amp; a == 1 &amp; is.na(b), &quot;A&quot;,
         ifelse(!is.na(b) &amp; b == 1 &amp; is.na(a), &quot;B&quot;, NA))))
# [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;   
#[11] &quot;A&quot;   

An alternative could be to use switch.

sapply(paste(df$a, df$b), switch,
       &quot;1 1&quot; = &quot;Both&quot;,
       &quot;1 NA&quot; = &quot;A&quot;,
       &quot;NA 1&quot; = &quot;B&quot;,
       NA)
#  1 NA   NA 1   1 NA   1 NA    1 1   NA 1   NA 1    1 1   NA 1   1 NA   1 NA 
#   &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

例如:

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 &amp; 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 |&gt; mutate(
  c = case_when(a == 1 &amp; b == 1 ~ &quot;Both&quot;,
                a == 1 &amp; is.na(b) ~ &quot;A&quot;,
                b == 1 &amp; is.na(a) ~ &quot;B&quot;,
                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

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:

确定