Дезагрегировать данные по дате с более высокого таймфрейма на более низкий с задержкой

#r

#r

Вопрос:

У меня есть два больших набора данных, один из которых имеет пару значение / временная метка a на очень коротком временном интервале, а другой — та же пара, но на дневном таймфрейме. Что я хотел бы сделать, так это применить дневное значение предыдущего дня к текущему дню на более низком таймфрейме. Например:

установите 1:

 timestamp           value
2019-10-03 23:24:00 2
2019-10-03 23:27:00 2
2019-10-03 23:30:00 3
2019-10-03 23:33:00 4
2019-10-03 23:36:00 4
2019-10-03 23:39:00 5
2019-10-03 23:42:00 5
2019-10-03 23:45:00 5
2019-10-03 23:48:00 5
2019-10-03 23:51:00 5
2019-10-03 23:54:00 5
2019-10-03 23:57:00 8
2019-10-04 0:00:00  8
2019-10-04 0:03:00  8
2019-10-04 0:06:00  8
2019-10-04 0:09:00  5
2019-10-04 0:12:00  5
2019-10-04 0:15:00  8
2019-10-04 0:18:00  6
2019-10-04 0:21:00  6
2019-10-04 0:24:00  6
2019-10-04 0:27:00  6
2019-10-04 0:30:00  7
2019-10-04 0:33:00  7
2019-10-04 0:36:00  7
2019-10-04 0:39:00  7
2019-10-04 0:42:00  7
  

установите 2:

 date    value2
2019-10-01  20
2019-10-02  40
2019-10-03  35
2019-10-04  14
2019-10-05  99
2019-10-06  23
2019-10-07  11
2019-10-08  67
2019-10-09  44
2019-10-10  32
2019-10-11  78
  

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

 timestamp         value value2
2019-10-03 23:24:00 2   40
2019-10-03 23:27:00 2   40
2019-10-03 23:30:00 3   40
2019-10-03 23:33:00 4   40
2019-10-03 23:36:00 4   40
2019-10-03 23:39:00 5   40
2019-10-03 23:42:00 5   40
2019-10-03 23:45:00 5   40
2019-10-03 23:48:00 5   40
2019-10-03 23:51:00 5   40
2019-10-03 23:54:00 5   40
2019-10-03 23:57:00 8   40
2019-10-04 0:00:00  8   35
2019-10-04 0:03:00  8   35
2019-10-04 0:06:00  8   35
2019-10-04 0:09:00  5   35
2019-10-04 0:12:00  5   35
2019-10-04 0:15:00  8   35
2019-10-04 0:18:00  6   35
2019-10-04 0:21:00  6   35
2019-10-04 0:24:00  6   35
2019-10-04 0:27:00  6   35
2019-10-04 0:30:00  7   35
2019-10-04 0:33:00  7   35
2019-10-04 0:36:00  7   35
2019-10-04 0:39:00  7   35
2019-10-04 0:42:00  7   35
  

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

Комментарии:

1. Верен ли ваш value2 «желаемый результат»? Разве они не должны быть 35 такими 14 ? Если это правильно, я не понимаю, как это работает.

2. Кроме того, была ли опечатка в том, что дни не были заполнены нулем в вашем наборе 2? Если это не было опечаткой, и ваши даты имеют разные форматы, то мое решение ниже не будет работать, и вам придется столкнуться с проблемой преобразования в даты, как показывает Ronak.

Ответ №1:

Вы можете вычесть -1 из даты в df1 и объединить данные с df2 помощью by date .

 library(dplyr)
library(lubridate)

df1 %>%
  mutate(timestamp = ymd_hms(timestamp), 
         date = as.Date(timestamp) - 1) %>%
  left_join(df2 %>% mutate(date = ymd(date)), by ='date')
  

Это возвращает

 #             timestamp value       date value2
#1  2019-10-03 23:24:00     2 2019-10-02     40
#2  2019-10-03 23:27:00     2 2019-10-02     40
#3  2019-10-03 23:30:00     3 2019-10-02     40
#4  2019-10-03 23:33:00     4 2019-10-02     40
#5  2019-10-03 23:36:00     4 2019-10-02     40
#6  2019-10-03 23:39:00     5 2019-10-02     40
#7  2019-10-03 23:42:00     5 2019-10-02     40
#8  2019-10-03 23:45:00     5 2019-10-02     40
#9  2019-10-03 23:48:00     5 2019-10-02     40
#10 2019-10-03 23:51:00     5 2019-10-02     40
#11 2019-10-03 23:54:00     5 2019-10-02     40
#12 2019-10-03 23:57:00     8 2019-10-02     40
#13 2019-10-04 00:00:00     8 2019-10-03     35
#14 2019-10-04 00:03:00     8 2019-10-03     35
#15 2019-10-04 00:06:00     8 2019-10-03     35
#16 2019-10-04 00:09:00     5 2019-10-03     35
#17 2019-10-04 00:12:00     5 2019-10-03     35
#18 2019-10-04 00:15:00     8 2019-10-03     35
#19 2019-10-04 00:18:00     6 2019-10-03     35
#20 2019-10-04 00:21:00     6 2019-10-03     35
#21 2019-10-04 00:24:00     6 2019-10-03     35
#22 2019-10-04 00:27:00     6 2019-10-03     35
#23 2019-10-04 00:30:00     7 2019-10-03     35
#24 2019-10-04 00:33:00     7 2019-10-03     35
#25 2019-10-04 00:36:00     7 2019-10-03     35
#26 2019-10-04 00:39:00     7 2019-10-03     35
#27 2019-10-04 00:42:00     7 2019-10-03     35
  

В базовом R вы можете написать тот же код, что и :

 df1$timestamp <- as.POSIXct(df1$timestamp, format = '%Y-%m-%d %T', tz = 'UTC')
df1$date <- as.Date(df1$timestamp) - 1
df2$date <- as.Date(df2$date)
merge(df1, df2, by = 'date')
  

Комментарии:

1. Блестяще. Я сделал эту проблему намного сложнее, чем нужно. Спасибо за помощь!

Ответ №2:

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

 df1$date <- sub("(.*) .*", "\1", df1$timestamp)
result <- merge(df1, df2, by = "date")
result$date <- NULL
  

Демонстрация с минимальными данными:

 df1 <- data.frame(
  timestamp = c("2019-10-03 23:24:00", "2019-10-03 23:27:00", "2019-10-04 0:15:00"),
  value = c(2, 2, 8)
)

df2 <- data.frame(
  date = c("2019-10-01", "2019-10-03", "2019-10-04"),
  value2 = c(20, 35, 14)
)

df1$date <- sub("(.*) .*", "\1", df1$timestamp)
result <- merge(df1, df2, by = 'date')
result$date <- NULL
  

Вывод:

 > result
            timestamp value value2
1 2019-10-03 23:24:00     2     35
2 2019-10-03 23:27:00     2     35
3  2019-10-04 0:15:00     8     14