Выберите строки выше и ниже максимального значения группы dplyr - PullRequest
0 голосов
/ 30 апреля 2020

У меня есть набор данных временного ряда с количеством различных групп (заданных значением строки в столбце группы) и столбцами переменных.

Я хочу выбрать строку с минимальным значением для данного столбца переменной для каждой группы, а затем выбрать 3 строки для дат «выше» и «ниже» (до и после) также минимального значения как само максимальное значение.

Окончательный результат должен составлять 7 строк для каждой группы, при этом минимальное значение равно 4-й строке. В идеале я хотел бы сделать это в dplyr ...

Dput:

structure(list(Country = c("ARG", "ARG", "ARG", "ARG", "ARG", 
"ARG", "ARG", "ARG", "ARG", "ARG", "ARG", "ARG", "ARG", "ARG", 
"ARG", "ARG", "ARG", "ARG", "ARG", "ARG", "ARG", "ARG", "ARG", 
"ARG", "ARG", "ARG", "ARG", "ARG", "ARG", "ARG", "ARG", "ARG", 
"ARG", "ARG", "ARG", "ARG", "ARG", "ARG", "ARG", "ARG", "ARG", 
"ARG", "ARG", "ARG", "ARG", "ARG", "ARG", "ARG", "ARG", "ARG", 
"ARG", "ARG", "ARG", "ARG", "ARG", "AUS", "AUS", "AUS", "AUS", 
"AUS", "AUS", "AUS", "AUS", "AUS", "AUS", "AUS", "AUS", "AUS", 
"AUS", "AUS", "AUS", "AUS", "AUS", "AUS", "AUS", "AUS", "AUS", 
"AUS", "AUS", "AUS", "AUS", "AUS", "AUS", "AUS", "AUS", "AUS", 
"AUS", "AUS", "AUS", "AUS", "AUS", "AUS", "AUS", "AUS", "AUS", 
"AUS", "AUS", "AUS", "AUS", "AUS", "AUS", "AUS", "AUS", "AUS", 
"AUS", "AUS", "AUS", "AUS", "AUS", "AUS"), Date = structure(c(18307, 
18308, 18309, 18310, 18311, 18312, 18313, 18314, 18315, 18316, 
18317, 18318, 18319, 18320, 18321, 18322, 18323, 18324, 18325, 
18326, 18327, 18328, 18329, 18330, 18331, 18332, 18333, 18334, 
18335, 18336, 18337, 18338, 18339, 18340, 18341, 18342, 18343, 
18344, 18345, 18346, 18347, 18348, 18349, 18350, 18351, 18352, 
18353, 18354, 18355, 18356, 18357, 18358, 18359, 18360, 18361, 
18307, 18308, 18309, 18310, 18311, 18312, 18313, 18314, 18315, 
18316, 18317, 18318, 18319, 18320, 18321, 18322, 18323, 18324, 
18325, 18326, 18327, 18328, 18329, 18330, 18331, 18332, 18333, 
18334, 18335, 18336, 18337, 18338, 18339, 18340, 18341, 18342, 
18343, 18344, 18345, 18346, 18347, 18348, 18349, 18350, 18351, 
18352, 18353, 18354, 18355, 18356, 18357, 18358, 18359, 18360, 
18361), class = "Date"), MobDecline = c(1.33333333333333, -4, 
-1.66666666666667, 7, 6.66666666666667, 5.33333333333333, 7, 
4, 5.66666666666667, -30.3333333333333, -32.6666666666667, 7.66666666666667, 
6.33333333333333, 8, 4.33333333333333, -1.33333333333333, 8, 
8, 8.33333333333333, 9.66666666666667, 12, 5.33333333333333, 
1.33333333333333, 9.66666666666667, 11.6666666666667, -2.33333333333333, 
8, 6.66666666666667, -14, -18.6666666666667, -14.3333333333333, 
-28.3333333333333, -32.3333333333333, -33.6666666666667, -70.3333333333333, 
-71.6666666666667, -75.3333333333333, -84, -84, -75.6666666666667, 
-76, -74.3333333333333, -72, -74.3333333333333, -75.3333333333333, 
-81, -72.6666666666667, -72.3333333333333, -70, -67.3333333333333, 
-70.3333333333333, -68.3333333333333, -68.3333333333333, -67.6666666666667, 
-71, 3.33333333333333, 1.66666666666667, 7.66666666666667, 6, 
6.66666666666667, 7.33333333333333, 10.3333333333333, 5.33333333333333, 
1.66666666666667, 8, 7.33333333333333, 7.66666666666667, 8, 11.6666666666667, 
7, 3, 5.33333333333333, 7.33333333333333, 7, 5.66666666666667, 
9.33333333333333, 2.66666666666667, 0.333333333333333, -8.66666666666667, 
5.66666666666667, 6.33333333333333, 6, 6.66666666666667, -2.66666666666667, 
-5.33333333333333, 1.33333333333333, -4.66666666666667, -7.66666666666667, 
-10.6666666666667, -11.3333333333333, -16.3333333333333, -21.3333333333333, 
-19.6666666666667, -31.3333333333333, -34.6666666666667, -38, 
-38, -40.3333333333333, -45.3333333333333, -43.3333333333333, 
-45.3333333333333, -45.6666666666667, -47.6666666666667, -45.6666666666667, 
-46, -47.3333333333333, -45, -46, -45, -42.3333333333333)), row.names = c(NA, 
-110L), groups = structure(list(Country = c("ARG", "AUS"), .rows = list(
    1:55, 56:110)), row.names = c(NA, -2L), class = c("tbl_df", 
"tbl", "data.frame"), .drop = TRUE), class = c("grouped_df", 
"tbl_df", "tbl", "data.frame"))

Желаемый результат:

Country Date         MobDecline
    ARG 2020-03-19  -33.6666667
    ARG 2020-03-20  -70.3333333
    ARG 2020-03-21  -71.6666667
    ARG 2020-03-22  -75.3333333
    ARG 2020-03-23  -84.0000000
    ARG 2020-03-24  -84.0000000
    ARG 2020-03-25  -75.6666667
    AUS 2020-03-30  -43.3333333
    AUS 2020-03-31  -45.3333333
    AUS 2020-04-01  -45.6666667
    AUS 2020-04-02  -47.6666667
    AUS 2020-04-03  -45.6666667
    AUS 2020-04-04  -46.0000000
    AUS 2020-04-05  -47.3333333

1 Ответ

1 голос
/ 30 апреля 2020

Я думаю, что ваш предполагаемый вывод неправильный: значение * max '(абсолютно значение!) ARG установлено на 2020-03-23-24), но вы показываете четыре строки перед ним и недостаточно строк после него.

Попробуйте:

dat %>%
  group_by(Country) %>%
  mutate(most = row_number() == which.max(abs(MobDecline))) %>%
  filter(zoo::rollapply(most, width = 7, FUN = any, fill = FALSE))
# # A tibble: 14 x 4
# # Groups:   Country [2]
#    Country Date       MobDecline most 
#    <chr>   <date>          <dbl> <lgl>
#  1 ARG     2020-03-20      -70.3 FALSE
#  2 ARG     2020-03-21      -71.7 FALSE
#  3 ARG     2020-03-22      -75.3 FALSE
#  4 ARG     2020-03-23      -84   TRUE 
#  5 ARG     2020-03-24      -84   FALSE
#  6 ARG     2020-03-25      -75.7 FALSE
#  7 ARG     2020-03-26      -76   FALSE
#  8 AUS     2020-03-30      -43.3 FALSE
#  9 AUS     2020-03-31      -45.3 FALSE
# 10 AUS     2020-04-01      -45.7 FALSE
# 11 AUS     2020-04-02      -47.7 TRUE 
# 12 AUS     2020-04-03      -45.7 FALSE
# 13 AUS     2020-04-04      -46   FALSE
# 14 AUS     2020-04-05      -47.3 FALSE

most можно удалить, оставив его здесь для демонстрации).

Использование zoo::rollapply является гораздо более короткой и гибкой версией, чем версия, основанная на повторяющихся lead и / или lag (что в ином случае является одним из способов решения этой проблемы).

Теперь используется abs(which.max(...)), который оба принимают максимальное абсолютное значение (в конце концов, вы сказали «максимум») и возвращают не более одной записи, даже если связаны. Если вам нужно +/- 3 строки, чтобы включить это (так что еще одна строка включена здесь), то мы можем попытаться использовать ==, но иногда это будет неудачно ( R FAQ 7.31 ), поэтому я Введу «допуск»:

dat %>%
  group_by(Country) %>%
  mutate(most = MobDecline <= (min(MobDecline) + tol)) %>%
  filter(zoo::rollapply(most, width = 7, FUN = any, fill = FALSE))
# # A tibble: 15 x 4
# # Groups:   Country [2]
#    Country Date       MobDecline most 
#    <chr>   <date>          <dbl> <lgl>
#  1 ARG     2020-03-20      -70.3 FALSE
#  2 ARG     2020-03-21      -71.7 FALSE
#  3 ARG     2020-03-22      -75.3 FALSE
#  4 ARG     2020-03-23      -84   TRUE 
#  5 ARG     2020-03-24      -84   TRUE 
#  6 ARG     2020-03-25      -75.7 FALSE
#  7 ARG     2020-03-26      -76   FALSE
#  8 ARG     2020-03-27      -74.3 FALSE
#  9 AUS     2020-03-30      -43.3 FALSE
# 10 AUS     2020-03-31      -45.3 FALSE
# 11 AUS     2020-04-01      -45.7 FALSE
# 12 AUS     2020-04-02      -47.7 TRUE 
# 13 AUS     2020-04-03      -45.7 FALSE
# 14 AUS     2020-04-04      -46   FALSE
# 15 AUS     2020-04-05      -47.3 FALSE
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...