Есть ли способ выделить группу, если ТОЛЬКО первое наблюдение соответствует критериям? - PullRequest
1 голос
/ 14 мая 2019

У меня есть фрейм данных:

ID = c(1,1,1,2,2,2,3,3,3,4,4,4,4)
VAR_1 = c(2,4,6,1,7,9,4,4,3,1,7,4,0)
VAR_2 = c(NA,NA,NA,NA,NA,20190101,20190101,20190101,NA,20190101,NA,NA,NA)
df2 = data.frame(ID,VAR_1,VAR_2)

И я хотел бы выделить из этого фрейма данных все строки для каждой группы (ID) ТОЛЬКО , если первое наблюдение по группе в VAR_2 имеет значение. В этом простом случае новое подмножество должно быть все строки из идентификаторов 3 и 4

Чтобы представить это лучше:

df                                       df_subset   

ID VAR_1 VAR_2                           ID VAR_1 VAR_2
1   2     NA                             3   4     20190101                           
1   4     NA                             3   4     20190101
1   6     NA                             3   3     NA
2   1     NA                             4   1     20190101
2   7     NA                             4   7     NA
2   9     20190101                       4   4     NA
3   4     20190101                       4   0     NA
3   4     20190101
3   3     NA
4   1     20190101
4   7     NA
4   4     NA
4   0     NA

Мне удается сделать это в несколько этапов (я подвожу оригинал, беря только первое наблюдение по группе, присваиваю VAR_1 специальное значение, заново объединяю и затем, наконец, фильтрую по специальному значению), но я хотел бы знать, если есть более простой, более элегантный (и, вероятно, более эффективный) способ. Мне не нужен VAR_1, поэтому его можно изменить, если необходимо, чтобы обеспечить более быстрое решение.

Любая помощь будет оценена.

1 Ответ

2 голосов
/ 14 мая 2019

Используя dplyr, мы можем group_by ID и выбирать группы, только если первое значение в каждой группе не является NA.

library(dplyr)

df2 %>%
  group_by(ID) %>%
  filter(!is.na(VAR_2[1L]))

#     ID VAR_1    VAR_2
#  <dbl> <dbl>    <dbl>
#1     3     4 20190101
#2     3     4 20190101
#3     3     3       NA
#4     4     1 20190101
#5     4     7       NA
#6     4     4       NA
#7     4     0       NA

Некоторые варианты для извлечения первого значения могут быть (спасибо @tmfmnk)

df2 %>%  group_by(ID) %>% filter(!is.na(first(VAR_2)))

ИЛИ

df2 %>% group_by(ID) %>%  filter(!is.na(nth(VAR_2, 1)))

То же самое с использованием базы R ave

df2[with(df2, ave(!is.na(VAR_2), ID, FUN = function(x) x[1L])), ]

или немного сложнее с split и subset

subset(df2, ID %in% names(na.omit(sapply(split(df2$VAR_2, df2$ID), head, 1))))
...