【问题标题】:Missing values in nested ifelse statements in RR中嵌套ifelse语句中的缺失值
【发布时间】:2014-07-12 04:45:59
【问题描述】:

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

我正在创建一个基于多个问题的答案的变量。每个问题可以有三个值: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
                )
            )
        )
    )

但是,此代码仅部分基于“ifelse”进行编码。例如,df$var 可能观察到“直觉”和“哲学”,但 var2 和 var3==1 的编码仍然是 NA。

对为什么会发生这种情况有任何想法吗?

【问题讨论】:

  • 也许你应该显示你的预期输出

标签: r if-statement


【解决方案1】:

比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

【讨论】:

  • 有趣的方法。之前我什至不知道row 和col 函数
  • 我很高兴我现在删除了我的答案。 :) 它会慢 50 倍。哈哈。
  • 虽然,公平地说,我怀疑这是一个真正需要优化速度的功能。正如他们所说,过早的优化是万恶之源。但是,很高兴知道所有选项。最好选择对代码维护者最有意义的一个。
【解决方案2】:

这是一种不用嵌套 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 扫描行以找到第一个 1 并使用该索引对响应值进行子集化。使用which 有助于处理NA 值。

【讨论】:

  • (+1) 很好地使用了矢量化。
【解决方案3】:

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

> 1 == NA
[1] NA

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

使用您的代码,如果1 之前出现NA(例如ID 2),那么ifelse 语句将只返回NA,而嵌套的FALSE ifelse 将永远不会被调用。

【讨论】:

    【解决方案4】:

    要回答您的问题,这是由于您的数据中存在 NA。这应该可以解决您的问题

    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

    【讨论】:

      猜你喜欢
      • 2021-09-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-10
      • 2013-08-03
      • 1970-01-01
      相关资源
      最近更新 更多