【问题标题】:How to find NAs in groups and create new column for data frame如何在组中查找 NA 并为数据框创建新列
【发布时间】:2014-02-02 18:40:48
【问题描述】:

我有一个由“ID”列和“Diff”列组成的数据框。 ID 列负责标记相应 Diff 值的组。 一个示例如下所示:

structure(list(ID = c(566, 566, 789, 789, 789, 487, 487, 11, 
11, 189, 189), Diff = c(100, 277, 529, 43, NA, 860, 780, 445, 
NA, 578, 810)), .Names = c("ID", "Diff"), row.names = c(9L, 10L, 
20L, 21L, 22L, 25L, 26L, 51L, 52L, 62L, 63L), class = "data.frame")

我的目标是在 Diff 列中搜索每个组的 NA 并创建一个新列,该列的每行具有“True”或“False”值,具体取决于相应组在 Diff 中是否具有 NA。

我试过了

x <- aggregate(Diff ~ ID, data, is.na)

y <- aggregate(Diff ~ ID, data, function(x) any(is.na(x)))

这个想法是根据 ID 合并结果。但是,以上都没有产生有用的结果。我知道 R 可以做到……在搜索了很长一段时间后,我问你怎么做 :)

【问题讨论】:

    标签: r aggregate na


    【解决方案1】:

    您可以使用plyrddply

    require(plyr)
    ddply(data, .(ID), transform, na_diff = any(is.na(Diff)))
    ##     ID Diff na_diff
    ## 1   11  445    TRUE
    ## 2   11   NA    TRUE
    ## 3  189  578   FALSE
    ## 4  189  810   FALSE
    ## 5  487  860   FALSE
    ## 6  487  780   FALSE
    ## 7  566  100   FALSE
    ## 8  566  277   FALSE
    ## 9  789  529    TRUE
    ## 10 789   43    TRUE
    ## 11 789   NA    TRUE
    

    【讨论】:

      【解决方案2】:

      与@dickoa 非常相似的解决方案,除了base

      do.call(rbind,by(data,data$ID,function(x)transform(x,na_diff=any(is.na(Diff)))))
      #         ID Diff na_diff
      # 11.51   11  445    TRUE
      # 11.52   11   NA    TRUE
      # 189.62 189  578   FALSE
      # 189.63 189  810   FALSE
      # 487.25 487  860   FALSE
      # 487.26 487  780   FALSE
      # 566.9  566  100   FALSE
      # 566.10 566  277   FALSE
      # 789.20 789  529    TRUE
      # 789.21 789   43    TRUE
      # 789.22 789   NA    TRUE
      

      同样,您可以通过以下方式避免transform

      data$na_diff<-with(data,by(Diff,ID,function(x) any(is.na(x)))[as.character(ID)])
      

      【讨论】:

      • 不错。您可以像这样简化代码do.call(rbind, by(data, data$ID, transform, na_diff = any(is.na(Diff))))
      【解决方案3】:

      您已经有两种可行的策略,但如果您对 R 相对较新并且不熟悉 plyr 的工作方式,那么这里还有一个在概念上可能更容易遵循。) p>

      我经常需要知道我在不同的变量中有多少NAs,所以这里有一个我使用标准的便利函数:

      sna <- function(x){
        sum(is.na(x))
      }
      

      从那里,我有时使用aggregate(),但有时我发现doBy 包中的?summaryBy 更方便。这是一个例子:

      library(doBy)
      z <- summaryBy(Diff~ID, data=my.data, FUN=sna)
      z
         ID Diff.sna
      1  11        1
      2 189        0
      3 487        0
      4 566        0
      5 789        1
      

      在此之后,您只需使用?merge 并将NAs 的计数转换为逻辑即可获得最终数据帧:

      my.data          <- merge(my.data, z, by="ID")
      my.data$Diff.sna <- my.data$Diff.sna>0
      my.data
          ID Diff Diff.sna
      1   11  445     TRUE
      2   11   NA     TRUE
      3  189  578    FALSE
      4  189  810    FALSE
      5  487  860    FALSE
      6  487  780    FALSE
      7  566  100    FALSE
      8  566  277    FALSE
      9  789  529     TRUE
      10 789   43     TRUE
      11 789   NA     TRUE
      

      【讨论】:

      • 谢谢。我认为所有答案都是合适的,并且会产生预期的结果。然而,这个是最容易理解的——正如引言中提到的那样:)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-19
      • 1970-01-01
      • 1970-01-01
      • 2020-01-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多