【问题标题】:Subset to only return complete cases on group basis with multiple rows子集仅返回具有多行的组的完整案例
【发布时间】:2019-04-17 10:30:34
【问题描述】:

如果我有一个 data.frame,DF,其中包含 5 个变量,这些变量具有 1 到 24 行之间的不同组 - 例如:

GROUP_ID    VAR_1    VAR_2    VAR_3    VAR_4    VAR_5
1             2        4        5        6        6
1             3        4        2        3        4
1             4       NA        6        6        3
1             3        2        1        2        4
2             9        8        2        7        1
2             2        3        3        2        6
2             2        5        8        9        2
3             2        1        5        6       NA
3            NA       NA        5        8        9
3             4        2        6        8        7

在这种情况下,完整的情况将被定义为在具有相应 group_ID 的任何行中的任何变量中都没有 NA 的组。在这个例子中,只有 GROUP_ID 2 代表一个完整的案例。

如何对 data.frame 进行子集化,以便找到具有完整案例的组并返回具有该组 ID 的所有行(在本示例中仅返回 GROUP_ID 2 的所有行)?

【问题讨论】:

    标签: r dplyr data.table plyr tidyr


    【解决方案1】:

    使用ave 的基本 R 方法是

    df[as.logical(ave(rowSums(is.na(df)), df$GROUP_ID, 
                         FUN = function(x) all(x == 0))), ]
    
    #  GROUP_ID VAR_1 VAR_2 VAR_3 VAR_4 VAR_5
    #5        2     9     8     2     7     1
    #6        2     2     3     3     2     6
    #7        2     2     5     8     9     2
    

    我们计算每一行中NAs 的数量,并过滤每个GROUP_IDall 的行值中包含0 个NA 的行。


    或者更简洁一点,结果相同

    df[ave(rowSums(is.na(df)) == 0, df$GROUP_ID, FUN = all), ]
    

    【讨论】:

      【解决方案2】:

      您可以为此使用dplyr。首先group_by 您的分组变量,然后使用filter_at 过滤您关心的完整案例的变量。这里我们使用starts_with 来选择所有VAR 变量(实际上是因为没有其他列我们可以使用filter_all)。然后我们使用all_vars 包装用于检查值是否不缺失的谓词。这基本上是说“对于每个组,检查all 每一列中的值是否不丢失。如果所有列都是这样,则保留该行(all_vars)。”

      library(tidyverse)
      tbl <- structure(list(GROUP_ID = c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 3L, 3L, 3L), VAR_1 = c(2L, 3L, 4L, 3L, 9L, 2L, 2L, 2L, NA, 4L), VAR_2 = c(4L, 4L, NA, 2L, 8L, 3L, 5L, 1L, NA, 2L), VAR_3 = c(5L, 2L, 6L, 1L, 2L, 3L, 8L, 5L, 5L, 6L), VAR_4 = c(6L, 3L, 6L, 2L, 7L, 2L, 9L, 6L, 8L, 8L), VAR_5 = c(6L, 4L, 3L, 4L, 1L, 6L, 2L, NA, 9L, 7L)), row.names = c(NA, -10L), class = c("tbl_df", "tbl", "data.frame"), spec = structure(list(cols = list(GROUP_ID = structure(list(), class = c("collector_integer", "collector")), VAR_1 = structure(list(), class = c("collector_integer", "collector")), VAR_2 = structure(list(), class = c("collector_integer", "collector")), VAR_3 = structure(list(), class = c("collector_integer", "collector")), VAR_4 = structure(list(), class = c("collector_integer", "collector")), VAR_5 = structure(list(), class = c("collector_integer", "collector"))), default = structure(list(), class = c("collector_guess", "collector"))), class = "col_spec"))
      
      tbl %>%
        group_by(GROUP_ID) %>%
        filter_at(vars(starts_with("VAR")), all_vars(all(!is.na(.))))
      #> # A tibble: 3 x 6
      #> # Groups:   GROUP_ID [1]
      #>   GROUP_ID VAR_1 VAR_2 VAR_3 VAR_4 VAR_5
      #>      <int> <int> <int> <int> <int> <int>
      #> 1        2     9     8     2     7     1
      #> 2        2     2     3     3     2     6
      #> 3        2     2     5     8     9     2
      

      reprex package (v0.2.1) 于 2018 年 11 月 14 日创建

      【讨论】:

      • 如果我在 data.frame 中有其他变量,但它们将被省略,因为只有 VAR_1 到 VAR_5 感兴趣,“all_vars”函数是否仅适用于在 filter_at 中指定的变量或data.frame 中的所有变量?
      • all_vars 适用于在 vars() 中选择的那些。未选择的变量将被忽略
      • 太棒了!谢谢!
      【解决方案3】:

      这是一个简单的单行基础 R 解决方案 -

      DF[ave(complete.cases(DF), DF$GROUP_ID, FUN = all), ]
      
        GROUP_ID VAR_1 VAR_2 VAR_3 VAR_4 VAR_5
      5        2     9     8     2     7     1
      6        2     2     3     3     2     6
      7        2     2     5     8     9     2
      

      【讨论】:

        【解决方案4】:

        这是另一个选项,使用每组 NA 的数量(如果您也感兴趣的话)。

        GROUP_ID.NA.COUNT <- tapply(rowSums(is.na(DF[paste("VAR", 1:5, sep = "_")])),
                                    DF$GROUP_ID, FUN = sum) # number of NA per group based on values from VAR_1 to VAR_5
        DF[DF$GROUP_ID %in% which(GROUP_ID.NA.COUNT == 0), ] # Subset to only return group with 0 NA based on values from VAR_1 to VAR_5
        
        # output
          GROUP_ID VAR_1 VAR_2 VAR_3 VAR_4 VAR_5
        5        2     9     8     2     7     1
        6        2     2     3     3     2     6
        7        2     2     5     8     9     2
        

        【讨论】:

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