Ищите предыдущую дату в датафрейме, у которой есть определенная категория столбца в R.

Вопрос или проблема

У меня есть следующий дата-фрейм:

      Date.POSIXct       Date      WeekDay DayCategory Hour Holidays   value
1 2018-05-01 00:00:00 2018-05-01      MA    MA-MI-JU    0        0      30
2 2018-05-01 01:00:00 2018-05-01      MA    MA-MI-JU    1        0      80
3 2018-05-01 02:00:00 2018-05-01      MA    MA-MI-JU    2        0      42
4 2018-05-01 03:00:00 2018-05-01      MA    MA-MI-JU    3        0      90
5 2018-05-01 04:00:00 2018-05-01      MA    MA-MI-JU    4        0      95
6 2018-05-01 05:00:00 2018-05-01      MA    MA-MI-JU    5        0       5

Категория дня группирует дни недели следующим образом: понедельники попадают в категорию LU. Вторники, среды и четверги попадают в категорию MA-MI-JU. Пятницы попадают в VI, субботы в SA и воскресенья в DO соответственно.

Я хотел бы найти значение для того же часа в предыдущий день (Date) с той же категорией дня, при этом праздники остаются в той же группе (например, если один экземпляр имеет праздник 0, но предыдущий день с той же категорией дня имеет 1, нам нужно искать предыдущий и т.д.)

В качестве промежуточного шага, чтобы понять процесс, я хотел бы добавить столбец PreviousDaySameDayCategory с Date предыдущего дня, который имеет ту же категорию дня, что и соответствующая строка. Иногда это будет просто та же дата минус семь дней (“LU”,”VI”,”SA”,”DO”), но в другие дни это будет просто один день.

Воспроизводимые данные:

library(lubridate)
Date.POSIXct <- seq(as.POSIXct("2018-05-01"), as.POSIXct("2018-05-31"), "hour")
mydf <- as.data.frame(Date.POSIXct)
mydf$Date <- as.Date(substr(as.character(mydf$Date.POSIXct),1,10))
mydf$WeekDay <- substr(toupper((weekdays(mydf$Date))),1,2)
mydf$DayCategory <-as.factor(ifelse(mydf$WeekDay == "MA" | mydf$WeekDay == "MI" | mydf$WeekDay == "JU", 
                                    "MA-MI-JU", mydf$WeekDay))
mydf$Hour <- hour(mydf$Date.POSIXct)
mydf$Holidays <- c(rep(0, 24*7),rep(1, 24*7), rep(0, 24*16+1))
set.seed(123)
mydf$myvalue <- sample.int(101,size=nrow(mydf),replace=TRUE)

Я вручную начал первые дни и создал вектор, как должно выглядеть решение:

  a <- rep(NA, 24)
  b <- mydf$value[1:24]
  c <- mydf$value[25:48]
  d <- rep(NA, 24)
  e <- rep(NA,24)
  f <- rep(NA,24)
  g <- rep(NA,24)
  h <- rep(NA,24)
  i <- mydf$value[169:192]
  solution <- c(a,b,c,d,e,f,g,h,i)
  solution

Я был бы признателен за любую подсказку в процессе мышления для решения подобных проблем, с которыми я сталкиваюсь относительно часто.

Я также опубликовал этот вопрос на Stack Over Flow, я думаю, что этот вид вопроса больше подходит для этого сообщества, чем для StackOverflow, верно? Я хотел бы удалить тот, который менее подходит для сообщества.

Если я вас правильно понимаю, вы хотите получить дату предыдущей той же категории дня, с тем же классом праздников, того же часа.

Если это так, возможно, вы можете попробовать:

1) Разделите строки по тому же часу, категории дня и группе праздников в одном кластере (или фильтре и т.д.)

2) Для каждого кластера, ранжируйте дату (первый день в группе – это 0, второй = 1 и т.д.) от наименьшего и т.д.

3) Для каждого ранга r, назначьте PreviousDaySameDayCategory, посмотрев на дату для строки r – 1, если r – 1 >= 0 в том же кластере

Это довольно просто реализовать с помощью dplyr. Пожалуйста, дайте мне знать, если следующее имеет смысл для вас.

(По некоторым причинам я не могу запустить ваше решение)

library(dplyr)
rankedDf <- mydf %>%
  group_by(DayCategory, Hour, Holidays) %>%
  arrange(DayCategory, Hour, Holidays, Date) %>%
  mutate(rowRank = order(Date), previousRowRank = order(Date) - 1) %>%
  left_join(., ., by = c("previousRowRank" = "rowRank", "DayCategory", "Hour", "Holidays")) %>%
  select(
    Date.POSIXct = Date.POSIXct.x,
    Date = Date.x,
    WeekDay = WeekDay.x,
    DayCategory,
    Hour,
    Holidays,
    myvalue = myvalue.x,
    PreviousDaySameDayCategory = Date.y,
    PreviousValueSameDayCategory = myvalue.y
  )
print.data.frame(rankedDf, nrow = 500)

Примечание: Я также включаю DayCategory и т.д. в упорядочивание, чтобы было удобнее понять, как это работает; код работает отлично и только с Date в качестве параметра.

Ответ или решение

Поиск значения предыдущего дня в датафрейме R по категории

В этом руководстве мы разберем, как в R найти значение для одного и того же часа даты в предыдущем дне с определенной категорией, при этом соблюдая условия для выходных дней. Исходя из предоставленного датафрейма и условий, мы постараемся добавить новый столбец PreviousDaySameDayCategory, который будет содержать дату предыдущего дня с той же категорией.

1. Подготовка данных

Сначала создадим датафрейм на основе предоставленного кода. Это позволит нам работать с аналогичным набором данных:

library(lubridate)
library(dplyr)

Date.POSIXct <- seq(as.POSIXct("2018-05-01"), as.POSIXct("2018-05-31"), "hour")
mydf <- as.data.frame(Date.POSIXct)
mydf$Date <- as.Date(substr(as.character(mydf$Date.POSIXct), 1, 10))
mydf$WeekDay <- substr(toupper((weekdays(mydf$Date))), 1, 2)
mydf$DayCategory <- as.factor(ifelse(mydf$WeekDay == "MA" | mydf$WeekDay == "MI" | mydf$WeekDay == "JU", 
                                      "MA-MI-JU", mydf$WeekDay))
mydf$Hour <- hour(mydf$Date.POSIXct)
mydf$Holidays <- c(rep(0, 24*7), rep(1, 24*7), rep(0, 24*16 + 1))
set.seed(123)
mydf$value <- sample.int(101, size = nrow(mydf), replace = TRUE)

2. Логика поиска предыдущего дня

Чтобы выполнить задачу, мы будем использовать следующий подход:

  1. Разделить строки по категориям DayCategory, Hour и Holidays.
  2. Для каждой группы отсортируйте по дате.
  3. Получите дату предыдущего дня с той же DayCategory и Holidays для каждого часа.

3. Реализация решения с использованием dplyr

Мы воспользуемся функцией dplyr для группировки и манипуляции данными:

rankedDf <- mydf %>%
  group_by(DayCategory, Hour, Holidays) %>%
  arrange(Date) %>%
  mutate(PreviousDaySameDayCategory = lag(Date, order_by = Date)) %>%
  ungroup() 

# Вывод результата
print(rankedDf)

Объяснение кода:

  • group_by(DayCategory, Hour, Holidays): Группируем наш датафрейм по категориям дня, часу и наличию выходного дня.
  • arrange(Date): Сортируем группы по дате.
  • mutate(PreviousDaySameDayCategory = lag(Date, order_by = Date)): Создаем новый столбец для хранения даты предыдущего дня с помощью функции lag(), которая возвращает значение из предыдущей строки, основываясь на сортировке по дате.

4. Учет значений

Если необходимо, мы можем дополнительно вернуть значения value для предыдущего дня, аналогично тому, как вы искали:

rankedDf <- mydf %>%
  group_by(DayCategory, Hour, Holidays) %>%
  arrange(Date) %>%
  mutate(PreviousDaySameDayCategory = lag(Date, order_by = Date),
         PreviousValueSameDayCategory = lag(value, order_by = Date)) %>%
  ungroup()

# Вывод результата
print(rankedDf)

Заключение

Таким образом, метод, который мы применили, позволяет извлечь предыдущие значения по определенным категориям из датафрейма. Этот подход предоставляет гибкость для дальнейшего анализа данных и упрощает процесс обработки данных в R. Если у вас возникнут дополнительные вопросы или потребность в уточнениях, не стесняйтесь обращаться за помощью.

Оцените материал
Добавить комментарий

Капча загружается...