如果我有一个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的所有行)?
答案 0 :(得分:1)
这是一个简单的单行基础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
答案 1 :(得分:0)
使用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
我们计算每行NA
的数量,并为每个NA
中的行值all
过滤具有0 GROUP_ID
的行。 / p>
或更简洁的结果相同
df[ave(rowSums(is.na(df)) == 0, df$GROUP_ID, FUN = all), ]
答案 2 :(得分:0)
您可以为此使用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创建
答案 3 :(得分:0)
这是另一种使用每组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