如何在ifelse中包含NA?

Tho*_*mas 31 if-statement r

我正在尝试ID基于其他列的值的逻辑语句创建列.例如,在以下数据框中

test <- structure(list(time = c(10L, 20L, NA, 30L), type = structure(c(1L, 
2L, 3L, NA), .Label = c("A", "B", "C"), class = "factor"), ID = c(NA, 
"1", NA, NA)), .Names = c("time", "type", "ID"), row.names = c(NA, 
-4L), class = "data.frame")
Run Code Online (Sandbox Code Playgroud)

看起来像

    time    type
1   10      A
2   20      B
3   NA      C
4   30      NA
Run Code Online (Sandbox Code Playgroud)

我想打一个新列ID包含所有值为1的time不在NA,所有type不属于A.我使用以下代码:

test$ID <- ifelse(is.na(test$time) | test$type == "A", NA, "1")
Run Code Online (Sandbox Code Playgroud)

这给出了结果

    time    type    ID
1   10      A       NA
2   20      B       1
3   NA      C       NA
4   30      NA      NA
Run Code Online (Sandbox Code Playgroud)

但是,此代码忽略NAin列type,从而产生一个NAin列值ID.我需要这个值为1,所以我需要的解决方案应该给:

    time    type    ID
1   10      A       NA
2   20      B       1
3   NA      C       NA
4   30      NA      1
Run Code Online (Sandbox Code Playgroud)

有人能告诉我怎么做这个吗?如果我能以某种方式改变is.na(test$type)返回的结果FALSE而不是,我可以使用我现有的代码TRUE,但我不知道该怎么做.或者,我现有代码的结构可能需要完全改变吗?我感谢任何帮助!

A5C*_*2T1 35

你不能真正NA与另一个值比较,所以使用==不起作用.考虑以下:

NA == NA
# [1] NA
Run Code Online (Sandbox Code Playgroud)

您可以将比较更改==%in%:

ifelse(is.na(test$time) | test$type %in% "A", NA, "1")
# [1] NA  "1" NA  "1"
Run Code Online (Sandbox Code Playgroud)

关于你的其他问题,

如果我能以某种方式改变is.na(test$type)返回的结果FALSE而不是,我可以使用我现有的代码TRUE,但我不知道该怎么做.

只是!用来否定结果:

!is.na(test$time)
# [1]  TRUE  TRUE FALSE  TRUE
Run Code Online (Sandbox Code Playgroud)


小智 7

听起来您希望 ifelse 语句在比较中将 NA 值解释为 FALSE 而不是 NA 。我使用以下函数来处理这种情况,因此我不必连续处理 NA 情况:

falseifNA <- function(x){
  ifelse(is.na(x), FALSE, x)
}

ifelse2 <- function(x, a, b){
  ifelse(falseifNA(x), a, b)
}
Run Code Online (Sandbox Code Playgroud)

您也可以将这些功能合二为一以提高效率。所以要返回你想要的结果,你可以使用:

test$ID <- ifelse2(is.na(test$time) | test$type == "A", NA, "1")
Run Code Online (Sandbox Code Playgroud)


Mat*_*rde 5

@AnandaMahto解决了为什么你得到这些结果并提供了最清楚的方法来获得你想要的东西.但另一种选择是使用identical而不是==.

test$ID <- ifelse(is.na(test$time) | sapply(as.character(test$type), identical, "A"), NA, "1")
Run Code Online (Sandbox Code Playgroud)

或使用isTRUE:

test$ID <- ifelse(is.na(test$time) | Vectorize(isTRUE)(test$type == "A"), NA, "1")
Run Code Online (Sandbox Code Playgroud)