【问题标题】:How to preserve NA values when using which.min() with apply()?将 which.min() 与 apply() 一起使用时如何保留 NA 值?
【发布时间】:2014-03-13 05:57:13
【问题描述】:

假设我有一个数据框,其中一些整列是NA,如下所示:

set.seed(0)
data <- data.frame(A = rnorm(10, 10, 1),
                   B = rnorm(10, 12, 2),
                   C = rep(NA, 10))

如果我在列中应用min(),我会得到我希望的输出:

apply(data, 2, min)
#        A        B        C 
# 8.460050 9.524923       NA 

但是,当我应用which.min() 时,我的输出是一个列表,而C 列给出的是integer(0)

apply(data, 2, which.min)
# $A
# [1] 6
# $B
# [1] 10
# $C
# integer(0)

我可以通过这个相当丑陋的解决方法让它看起来像我想要的那样:

which.mins <- unlist(apply(data, 2, which.min))
which.mins[names(data)[!(names(data) %in% names(which.mins))]] <- NA
which.mins
#  A  B  C 
#  6 10 NA 

有没有更好的方法来做到这一点,可以模仿我在使用apply()min() 时得到的输出?

【问题讨论】:

    标签: r na


    【解决方案1】:

    你说得对,如果 x 没有非 NA,which.min 将返回 0。你仍然可以像这样使用applywhich.min

    apply(data, 2, function(x) {if (all(is.na(x))) {NA}  else {which.min(x)} }) 
    

    【讨论】:

    • 比我快 6 秒 =) 我打算建议 which.mins
    • 完美!此外,很高兴了解 all() 函数——它可以派上用场。谢谢!
    【解决方案2】:

    请注意,在 data.frame 上调用 apply 会导致在应用函数之前将 data.frame 强制转换为矩阵。你应该改用sapply(或vapply),否则你可能会得到奇怪的错误,因为你的data.frame的所有列都被强制转换为一个通用类型(通常是字符)。

    只需测试which.min 的结果长度是否为零,在这种情况下返回NA

    > # if() evaluates to FALSE if length(wm) is 0 because as.logical(0) is FALSE
    > sapply(data, function(x) if(length(wm <- which.min(x))) wm else NA)
     A  B  C 
     6 10 NA
    

    【讨论】:

    • 感谢有关 apply() 将 data.frame 强制转换为矩阵的提示 - 这是需要注意的四个。
    【解决方案3】:

    第一个示例没有给出 NA 值,因为它检测向量中的 NA 并将它们作为最小值返回,它给出 NA 是因为数据框的 C 列中没有数字,所以它不能返回number 到数字向量min 的第 3 位返回。 which.min() 返回最小值位置列表的列表:

    str(apply(data, 2, which.min)[1])
    List of 1
     $ A: int 6
    

    由于 C 列中没有最小值,它返回一个长度为 0 的列表,为您提供integer(0) 结果。

    如果您正在尝试这样做,那么您的解决方法很好。或者,您可以将整个内容包装在一个函数中

    whichMinNAs <- function(x){
      if(FALSE %in% is.na(x)){
        return(which.min(x))
      } else {
        return(NA)
      }
    }
    
    apply(data, 2, whichMinNAs)
    
     A  B  C 
     6 10 NA
    

    【讨论】:

      【解决方案4】:

      以下是解决方法的示例:

      apply(data, 2, FUN=function(x) ifelse(length(test<-which.min(x))>0, test, NA))
      
      > apply(data, 2, FUN=function(x) ifelse(length(test<-which.min(x))>0, test, NA))
       A  B  C 
       6 10 NA
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-10-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-07-10
        相关资源
        最近更新 更多