подмножество данных панели, зависящее от последовательных строк длины

Я застрял, пытаясь подмножить некоторые данные панели, то есть идентификаторы внутри группы, используя dplyr.

Я хочу точно определить все id в каждой группе, grp, которая имеет ряд NUM с минимальным значением меньше 2 и максимальным значением больше 2. Ниже я построил минимальный рабочий пример, который должен иллюстрировать проблема.

Я работал с filter(), row_number() == c(1,n()) и пытался разделить их и объединить, то есть разные типы _join, снова вместе, но я застрял, и теперь я обращаюсь за помощью к сообществу SO.

Что я имею

tibble вот так,

df <- tibble(id = rep(0:1, c(8, 13)), grp = rep(c("01", "02"), c(13, 8)),
             NUM = c(-4, -3, -2, -1, 1, 2, 3, 4, -3, -2, -1,
                      1, 2, -3, -2, -1, 1, 2, 3, 4, 5)) %>% group_by(id, grp)
df %>% print(n=21)
#> # A tibble: 21 x 3
#> # Groups:   id, grp [3]
#>       id   grp   NUM
#>    <int> <chr> <dbl>
#>  1     0    01    -4
#>  2     0    01    -3
#>  3     0    01    -2
#>  4     0    01    -1
#>  5     0    01     1
#>  6     0    01     2
#>  7     0    01     3
#>  8     0    01     4
#>  9     1    01    -3
#> 10     1    01    -2
#> 11     1    01    -1
#> 12     1    01     1
#> 13     1    01     2
#> 14     1    02    -3
#> 15     1    02    -2
#> 16     1    02    -1
#> 17     1    02     1
#> 18     1    02     2
#> 19     1    02     3
#> 20     1    02     4
#> 21     1    02     5

Что я пытаюсь получить / желаемый результат

df_out <- tibble(id = rep(0:1, c(9, 8)),
             grp = rep(c("01", "02"), c(9, 8)),
             NUM = c(-4, -3, -2, -1, 1, 2, 3,
           4, 5, -3, -2, -1, 1, 2, 3, 4, 5)) %>%  group_by(id, grp)
df_out
#> # A tibble: 17 x 3
#> # Groups:   id, grp [3]
#>       id   grp   NUM
#>    <int> <chr> <dbl>
#>  1     0    01    -4
#>  2     0    01    -3
#>  3     0    01    -2
#>  4     0    01    -1
#>  5     0    01     1
#>  6     0    01     2
#>  7     0    01     3
#>  8     0    01     4
#>  9     1    02    -3
#> 10     1    02    -2
#> 11     1    02    -1
#> 12     1    02     1
#> 13     1    02     2
#> 14     1    02     3
#> 15     1    02     4
#> 16     1    02     5

person Eric Fail    schedule 25.01.2018    source источник


Ответы (1)


Вот так?

library(dplyr)
filter(df, any(NUM > 2) & any(NUM < -2))

# A tibble: 16 x 3
# Groups:   id, grp [2]
      id grp     NUM
   <int> <chr> <dbl>
 1     0 01    -4.00
 2     0 01    -3.00
 3     0 01    -2.00
 4     0 01    -1.00
 5     0 01     1.00
 6     0 01     2.00
 7     0 01     3.00
 8     0 01     4.00
 9     1 02    -3.00
10     1 02    -2.00
11     1 02    -1.00
12     1 02     1.00
13     1 02     2.00
14     1 02     3.00
15     1 02     4.00
16     1 02     5.00

Кроме того, если нужно подмножить точные значения, скажем, первое NUM равно -3, а последнее NUM равно 5, т. е. строки 9-16 в исходных данных, это можно сделать следующим образом:

df %>%
  group_by(id, grp) %>%
  mutate(first = first(NUM)
        ,last = last(NUM)) %>%
  filter(-3 == first & 5 == last) %>%
  select(-first, -last)  
#> # A tibble: 8 x 3
#> # Groups:   id, grp [1]
#>      id   grp   NUM
#>   <int> <chr> <dbl>
#> 1     1    02    -3
#> 2     1    02    -2
#> 3     1    02    -1
#> 4     1    02     1
#> 5     1    02     2
#> 6     1    02     3
#> 7     1    02     4
#> 8     1    02     5

Вышеизложенное вдохновлено этим ответом SO.

person markus    schedule 25.01.2018
comment
Спасибо за быстрый ответ! Я понял, что сделал минимальный рабочий пример слишком минимальным. У меня есть случаи, когда строки NUM не равны, например. -3, -2, -1, 1, 2, которые тогда не должны учитываться. Я обновлю свой mwe до чего-то вроде этого df <- tibble(id = rep(0:1, c(8, 13)), grp = rep(c("01", "02"), c(13, 8)), NUM = c(-4, -3, -2, -1, 1, 2, 3, 4, -3, -2, -1, 1, 2, -3, -2, -1, 1, 2, 3, 4, 5)) %>% group_by(id, grp) (но это может занять минуту, так как мне придется все обдумать) - person Eric Fail; 25.01.2018
comment
можно даже сократить до filter(df, any(NUM > abs(2))) - person Eric Fail; 26.01.2018
comment
@EricFail, спасибо за редактирование, но я бы посоветовал вам опубликовать его как еще один ответ на вопрос. Также 6-я строка, вероятно, должна быть select(-first, -last). - person markus; 26.01.2018