如何在ifelse中包含NA?

时间:2014-02-27 17:48:39

标签: r if-statement

我正在尝试基于其他列的值的逻辑语句创建列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")

看起来像

    time    type
1   10      A
2   20      B
3   NA      C
4   30      NA

我想为不是ID的所有time以及不是NA的所有type制作一个包含值1的新列A 。我正在使用以下代码:

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

这将结果显示为

    time    type    ID
1   10      A       NA
2   20      B       1
3   NA      C       NA
4   30      NA      NA

但是,此代码会忽略NA列中的type,从而导致NA列中的ID值。我需要这个值为1,所以我需要的解决方案应该给出:

    time    type    ID
1   10      A       NA
2   20      B       1
3   NA      C       NA
4   30      NA      1

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

5 个答案:

答案 0 :(得分:31)

您无法将NA与其他值进行真正比较,因此使用==将无效。请考虑以下事项:

NA == NA
# [1] NA

您可以将比较从==更改为%in%

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

关于你的其他问题,

  

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

只需使用!来否定结果:

!is.na(test$time)
# [1]  TRUE  TRUE FALSE  TRUE

答案 1 :(得分:5)

答案 2 :(得分:3)

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

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

ifelse2 <- function(x, a, b){
  ifelse(falseifNA(x), a, b)
}

您还可以将这些功能合并为一个以提高效率。因此,要返回您想要的结果,您可以使用:

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

答案 3 :(得分:1)

所以,我听说这可行:

Data$X1<-as.character(Data$X1)
Data$GEOID<-as.character(Data$BLKIDFP00)
Data<-within(Data,X1<-ifelse(is.na(Data$X1),GEOID,Data$X2)) 

但是我承认我只有间歇性的运气。

答案 4 :(得分:1)

您也可以尝试elseif。

x <- 1
if (x ==1){
    print('same')
} else if (x > 1){
    print('bigger')
} else {
    print('smaller')
}