Удаление строк с датами, обусловленными определенными идентификаторами - PullRequest
0 голосов
/ 14 февраля 2019

По сути, у меня есть фрейм данных, который содержит идентификаторы, Dates, VolumeX и VolumeY.

Я хочу разделить фрейм данных VolumeX до и после максимальной даты VolumeY, определенной для идентификатора.

отл.

df выглядит (с множеством разных идентификаторов):

ID  Date            VolX   VolY
1   2018 - 02- 01   5      -
1   2018 - 03- 01   6      -
1   2018 - 08- 01   3      -
1   2018 - 10- 01   1      -
1   2017 - 02- 01   -      1
1   2014 - 10- 01   -      0
1   2014 - 11- 01   -      5
1   2018 - 02- 01   -      0 

Так что для максимальной даты VolY для каждого идентификатора я хотел бы разделить фрейм данных на два: before ипосле этой даты для каждого ID можно суммировать VolX до и после максимальной даты VolY.

Похоже, это должен быть какой-то вложенный цикл for.Я могу извлечь максимальные даты и общий объем ... просто с трудом выбирая идентификатор

1 Ответ

0 голосов
/ 14 февраля 2019

Это то, что вам нужно?

library(dplyr)

df %>%
  replace(., . == "-", NA) %>%
  mutate(Date = as.Date(gsub("\\s", "", Date))) %>%
  mutate_at(vars(VolX, VolY), as.numeric) %>%
  group_by(ID, Before_After = cumsum(c(0, lag(+(Date == max(Date)))[-1]))) %>%
  mutate(
    sum_Volx = sum(VolX[Date != max(Date)], na.rm = T),
    sum_VolY = sum(VolY[Date != max(Date)], na.rm = T)
  ) %>% ungroup() %>% select(-Before_After)

Вывод:

# A tibble: 8 x 6
     ID Date        VolX  VolY sum_Volx sum_VolY
  <int> <date>     <dbl> <dbl>    <dbl>    <dbl>
1     1 2018-02-01     5    NA       14        0
2     1 2018-03-01     6    NA       14        0
3     1 2018-08-01     3    NA       14        0
4     1 2018-10-01     1    NA       14        0
5     1 2017-02-01    NA     1        0        6
6     1 2014-10-01    NA     0        0        6
7     1 2014-11-01    NA     5        0        6
8     1 2018-02-01    NA     0        0        6

Вы также можете сделать отдельные столбцы для до / после, например:

df %>%
  replace(., . == "-", NA) %>%
  mutate_at(vars(VolX, VolY), as.numeric) %>%
  group_by(ID) %>%
  mutate(
    Date = as.Date(gsub("\\s", "", Date)),
    Before_After = cumsum(c(0, lag(+(Date == max(Date)))[-1])),
    sum_Volx_Before = sum(VolX[Date != max(Date) & Before_After == 0], na.rm = T),
    sum_VolY_Before = sum(VolY[Date != max(Date) & Before_After == 0], na.rm = T),
    sum_Volx_After = sum(VolX[Date != max(Date) & Before_After == 1], na.rm = T),
    sum_VolY_After = sum(VolY[Date != max(Date) & Before_After == 1], na.rm = T)
  ) %>% ungroup() %>% select(-Before_After)

Вывод:

# A tibble: 8 x 8
     ID Date        VolX  VolY sum_Volx_Before sum_VolY_Before sum_Volx_After sum_VolY_After
  <int> <date>     <dbl> <dbl>           <dbl>           <dbl>          <dbl>          <dbl>
1     1 2018-02-01     5    NA              14               0              0              6
2     1 2018-03-01     6    NA              14               0              0              6
3     1 2018-08-01     3    NA              14               0              0              6
4     1 2018-10-01     1    NA              14               0              0              6
5     1 2017-02-01    NA     1              14               0              0              6
6     1 2014-10-01    NA     0              14               0              0              6
7     1 2014-11-01    NA     5              14               0              0              6
8     1 2018-02-01    NA     0              14               0              0              6

С другой стороны, вы можете просто создать 2 отдельных новых фрейма данных в вашей среде с именами Before и After, которые буквально исключают максимальную дату и суммируютинформация, как показано ниже:

df_list <- df %>%
  replace(., . == "-", NA) %>%
  mutate_at(vars(VolX, VolY), as.numeric) %>%
  group_by(ID) %>%
  mutate(
    Date = as.Date(gsub("\\s", "", Date)),
    Before_After = cumsum(c(0, lag(+(Date == max(Date)))[-1]))
  ) %>%
  filter(!Date == max(Date)) %>%
  group_by(ID, Before_After) %>%
  summarise(
    sum_VolX = sum(VolX, na.rm = T),
    sum_VolY = sum(VolY, na.rm = T)
  ) %>%
  split(., .$Before_After)

names(df_list) <- c("Before", "After")
list2env(df_list, envir = .GlobalEnv)

Давайте рассмотрим по очереди:

  • Сначала мы replace - знаки NA (не строгонеобходимо, чтобы избежать ошибок в дальнейшем);
  • после этого мы преобразуем VolX и VolY в числовые значения;
  • , затем группируем по ID, чтобы все применялось к каждой группе.отдельно;
  • после этого мы преобразуем Date в правильный Date формат;
  • , тогда это важная часть: мы вычисляем столбец flag Before_After, где сначала мы помечаем 1 если в предыдущем ряду была соблюдена максимальная дата;после этого мы вычисляем кумулятивную сумму такого столбца, чтобы все до этого события равнялось 0, а все после 1;
  • , затем мы отфильтровывали максимальное значение Date;
  • и снова группировали по ID и Before_After индикатор;
  • мы сжимаем фрейм данных с summarise, чтобы он содержал только сумму соответствующих столбцов;
  • мы превращаем фрейм данных в 2 разных, разбивая столбец Before_After;
  • , так как полученный результат представляет собой список из 2 фреймов данных, нам нужно перенести их в глобальную среду,поэтому сначала мы присваиваем имена каждому из них, а затем превращаем их в «правильные» фреймы данных.

Вывод:

Before

# A tibble: 1 x 4
# Groups:   ID [1]
     ID Before_After sum_VolX sum_VolY
  <int>        <dbl>    <dbl>    <dbl>
1     1            0       14        0

After

# A tibble: 1 x 4
# Groups:   ID [1]
     ID Before_After sum_VolX sum_VolY
  <int>        <dbl>    <dbl>    <dbl>
1     1            1        0        6

Обратите внимание, что 0 соответствует Before иОт 1 до After.

...