R中嵌套的ifelse语句中缺少值

时间:2014-05-22 23:39:33

标签: r if-statement

在某个时间点,我遇到了这个问题......并解决了它。但是,由于这是一个反复出现的问题,我现在已经忘记了解决方案,希望这个问题能够为我和其他人提供澄清:)

我正在创建一个基于几个问题的答案的变量。每个问题可以有三个值:1,2或NA。对于每次观察,1和2是相互排斥的。

我只是想创建一个变量,它是用" 1"编码的选项的复合。为每个人,并根据该代码给它一个值。

所以,让我说我有df

ID   var1    var2   var3   var4
1    1       2      NA     NA
2    NA      NA     2      1
3    2       1      NA     NA
4    2       NA     1      NA

然后我尝试根据以下语句重新编码:

df$var <- 
    ifelse(
        as.numeric(df$var1) == 1,
        "Gut instinct",
        ifelse(
            as.numeric(df$var2) == 1,
            "Data",
            ifelse(
                as.numeric(df$var3) == 1,
                "Science",
                ifelse(
                    as.numeric(df$var4) == 1,
                    "Philosophy",
                    NA
                )
            )
        )
    )

但是,此代码仅基于&#34; ifelse&#34;的PARTIALLY代码。例如,df$var可能会观察到肠道本能&#39;和哲学&#39;但是var2var3==1的编码仍然是NA。

有关为何会发生这种情况的任何想法?

4 个答案:

答案 0 :(得分:5)

apply更快的替代方案(使用@ MrFlick的数据):

vals <- c("Gut", "Data", "Science", "Phil")
intm <- dd[-1]==1 & !is.na(dd[-1])
dd$resp <- NA
dd$resp[row(intm)[intm]] <- vals[col(intm)[intm]]

快多少?在100万行:

#row/col assignment
user  system elapsed 
0.99    0.02    1.02 

#apply
 user  system elapsed 
11.98    0.04   12.30 

在相同的数据集上尝试时给出相同的结果:

identical(flick$resp,latemail$resp)
#[1] TRUE

答案 1 :(得分:4)

这是一种没有嵌套ifelse语句的方法

#your data
dd<-data.frame(ID = 1:4, 
    var1 = c(1, NA, 2, 2), 
    var2 = c(2, NA, 1, NA), 
    var3 = c(NA, 2, NA, 2), 
    var4 = c(NA, 1, NA, NA)
)

resp <- c("Gut","Data","Sci","Phil")[apply(dd[,-1]==1,1,function(x) which(x)[1])]
cbind(dd, resp)

我使用apply扫描行以查找第一行并使用该索引对响应值进行子集化。使用which有助于处理NA值。

答案 2 :(得分:3)

这是因为ifelse(和==)对NA有特殊行为。具体来说,R不希望告诉您NA1(或其他任何内容)不同,因为NA通常用于表示可能是任何东西,甚至可能是1

> 1 == NA
[1] NA

> ifelse(NA == 1, "yes", "no")
[1] NA

使用您的代码,如果NA发生在1之前(例如ID 2),则ifelse语句将返回NA,并且永远不会调用嵌套的FALSE ifelse

答案 3 :(得分:1)

要回答您的问题,这取决于您的数据中的NAs。这应该排除你的问题

df <- data.frame( ID=1:4, var1= c(1, NA, 2, 2), var2= c(2, NA, 1, NA),
var3=c(NA,2,NA,2), var4=c(NA, 1, NA, NA))

df$var<-ifelse(as.numeric(df$var1)==1&!is.na(df$var1),"Gut instinct", 
           ifelse(as.numeric(df$var2)==1&!is.na(df$var2),"Data",
                  ifelse(as.numeric(df$var3)==1&!is.na(df$var3),"Science",
                      ifelse(as.numeric(df$var4)==1&!is.na(df$var4),"Philosophy",NA))))

但是,我会发现将数据重塑为“矩阵”更容易。而不是一张桌子,用矢量做。

data <- df
library(reshape2)
long <- melt(data, id.vars="ID")
long

这会给你一个矩阵。将var标题转换为更有意义的标题。

library(stringr)
long$variable <- str_replace(long$variable, "var1", "Gut Instinct")
long$variable <- str_replace(long$variable, "var2", "Data")
long$variable <- str_replace(long$variable, "var3", "Science")
long$variable <- str_replace(long$variable, "var4", "Philosophy")

现在,您可以根据每个结果决定做什么

long$var <- ifelse(long$value==1, long$variable, NA)

并将其转换回原始版本,如果您想要那样的话

reshape(data=long, timevar="ID",idvar=c("var", "variable"), v.names = "value", direction="wide")

HTH