Подмножество, чтобы возвращать только полные случаи на групповой основе с несколькими строками - PullRequest
0 голосов
/ 14 ноября 2018

Если у меня есть 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

В этом случае полный случай будет определяться как группы без NA в любой из переменных в любой из строк с соответствующим group_ID. В этом примере только GROUP_ID 2 будет представлять полный регистр.

Как мне поместить data.frame таким образом, чтобы он находил группы с полными регистрами и возвращал все строки с этим идентификатором группы (в этом примере возвращаются только все строки для GROUP_ID 2)?

Ответы [ 4 ]

0 голосов
/ 14 ноября 2018

Вот еще один вариант, использующий число 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
0 голосов
/ 14 ноября 2018

Вы можете использовать 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

Создано в 2018-11-14 пакетом Представ (v0.2.1)

0 голосов
/ 14 ноября 2018

Вот простое однострочное базовое решение 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
0 голосов
/ 14 ноября 2018

Базовый подход R с использованием ave будет

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 с в каждой строке и фильтруем строки, которые имеют 0 NA для all значений строк в каждом GROUP_ID.


Или немного более кратко, что дает тот же результат

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