Удалить строки после группы по значению столбца - PullRequest
3 голосов
/ 31 марта 2020

У меня есть набор данных с разными идентификаторами, датой, количеством. Все идентификаторы имеют одинаковую точную дату начала, однако некоторые имеют начальные количества 0, поэтому в основном дата начала должна быть позже.

Я пытаюсь отфильтровать строки так, чтобы каждый идентификатор

df <- data.frame(ID = c("1", "1", "1", "1", "1", "1",
                        "2", "2", "2", "2", "2", "2",
                        "3", "3", "3", "3", "3", "3"),
                 Date = c(seq(as.Date("2000/1/1"), by = "month", length.out = 6),
                          seq(as.Date("2000/1/1"), by = "month", length.out = 6),
                          seq(as.Date("2000/1/1"), by = "month", length.out = 6)),
                 QTY = c(0, 0, 0, 40, 0, 60, 50, 55, 0, 70, 88, 64, 0, 43, 43, 0, 99, 99))

Так что в основном в приведенном выше примере с df я хочу, чтобы идентификатор № 1 начинался с четвертого значения QTY, а идентификатор № 3 начинался со второго значения QTY.

Я пытался использовать group by и изменять его новый столбец с ifelse, но у меня была некоторая ошибка.

Мой ожидаемый df должен быть преобразованием из первого в следующий, так что просто удаляйте первые строки с нулями для каждого идентификатора, пока QTY не начнет отображаться. более 0

df <- data.frame(ID = c("1", "1", "1",
                        "2", "2", "2", "2", "2", "2",
                        "3", "3", "3", "3", "3"),
                 Date = c(seq(as.Date("2000/4/1"), by = "month", length.out = 3),
                          seq(as.Date("2000/1/1"), by = "month", length.out = 6),
                          seq(as.Date("2000/2/1"), by = "month", length.out = 5)),
                 QTY = c(40, 0, 60, 50, 55, 0, 70, 88, 64, 43, 43, 0, 99, 99))

Ответы [ 2 ]

3 голосов
/ 31 марта 2020

Если данные такие же, как в вашем примере (т. Е. Нет NA или отрицательных значений), достаточно только этого base решения:

df[with(df, ave(QTY, ID, FUN = cumsum)) > 0, ]

или subset(df, ave(QTY, ID, FUN = cumsum) > 0), но, вероятно, чуть-чуть медленнее.

Вывод:

   ID       Date QTY
4   1 2000-04-01  40
5   1 2000-05-01   0
6   1 2000-06-01  60
7   2 2000-01-01  50
8   2 2000-02-01  55
9   2 2000-03-01   0
10  2 2000-04-01  70
11  2 2000-05-01  88
12  2 2000-06-01  64
14  3 2000-02-01  43
15  3 2000-03-01  43
16  3 2000-04-01   0
17  3 2000-05-01  99
18  3 2000-06-01  99

Это то же самое, что и dplyr:

library(dplyr)

df %>%
  group_by(ID) %>%
  filter(cumsum(QTY) > 0)
2 голосов
/ 31 марта 2020

Попробуйте это. Основная идея c заключается в вычислении cumsum ненулевого QTY для каждого ID с течением времени. Затем отфильтруйте obs с помощью cumsum == 0:

library(dplyr)

df <- data.frame(ID = c("1", "1", "1", "1", "1", "1",
                        "2", "2", "2", "2", "2", "2",
                        "3", "3", "3", "3", "3", "3"),
                 Date = c(seq(as.Date("2000/1/1"), by = "month", length.out = 6),
                          seq(as.Date("2000/1/1"), by = "month", length.out = 6),
                          seq(as.Date("2000/1/1"), by = "month", length.out = 6)),
                 QTY = c(0, 0, 0, 40, 0, 60, 50, 55, 0, 70, 88, 64, 0, 43, 43, 0, 99, 99))

df %>% 
  arrange(ID, Date) %>% 
  group_by(ID) %>% 
  mutate(cum_non_zero = cumsum(QTY > 0)) %>% 
  filter(cum_non_zero > 0)
#> # A tibble: 14 x 4
#> # Groups:   ID [3]
#>    ID    Date         QTY cum_non_zero
#>    <fct> <date>     <dbl>        <int>
#>  1 1     2000-04-01    40            1
#>  2 1     2000-05-01     0            1
#>  3 1     2000-06-01    60            2
#>  4 2     2000-01-01    50            1
#>  5 2     2000-02-01    55            2
#>  6 2     2000-03-01     0            2
#>  7 2     2000-04-01    70            3
#>  8 2     2000-05-01    88            4
#>  9 2     2000-06-01    64            5
#> 10 3     2000-02-01    43            1
#> 11 3     2000-03-01    43            2
#> 12 3     2000-04-01     0            2
#> 13 3     2000-05-01    99            3
#> 14 3     2000-06-01    99            4

, созданного в 2020-03-31 пакетом prex (v0.3.0)

...