#r #dataframe #datetime #time-series #subset
#r #dataframe #дата-время #временные ряды #подмножество
Вопрос:
У меня есть data.frame информации о погоде по этой ссылке https://www.dropbox.com/s/60p93cmhgdi93yd/weather(2).xlsx?dl=0
Эта информация о погоде записывается каждые 4-6 минут (в зависимости от дней). Я хотел извлечь определенный период времени из data.frame среди двух последовательных дней. Например, я хотел бы извлечь период времени с 9:45 утра 2018-4-9 по 9:45 утра 2018-4-10 и с 9:45 утра 2018-4-23 по 9:45 утра 2018-4-24, …..
Я также создал поддельный data.frame, как рекомендовано, но мой фактический data.frame содержит более 60 групп по два последовательных дня:
df1 <- data.frame(
datetime = seq(
as.POSIXct("2018-4-9 00:00"), as.POSIXct("2018-4-10 00:00"), by = "60 min"))
df2 <- data.frame(
datetime = seq(
as.POSIXct("2018-4-23 00:00"), as.POSIXct("2018-4-24 00:00"), by = "60 min"))
df3 <- data.frame(
datetime = seq(
as.POSIXct("2018-5-7 00:00"), as.POSIXct("2018-5-8 00:00"), by = "60 min"))
df <- rbind(df,df2,df3)
Я подумал о нескольких способах сделать это:
- Я могу использовать пакет ‘lubridate’ для преобразования времени в числовую форму, чтобы я мог определить продолжительность определенных чисел, которые нужно извлечь. Но мне также нужно сгруппировать каждые две последовательные даты вместе, чтобы рассчитать продолжительность. У меня был такой код
daystart <- hm("0:0")
weather$date1 <- sort(as.Date(weather$Date))
a <- split(weather$date1,cumsum(c(TRUE,diff(weather$date1)>1)))
weather <- data.frame(weather,a)
#this does not work
weather <- weather %>%
group_by(group #the grouped consecutive days) %>%
mutate(dur = as.numeric(Time-daystart)) %>%
filter(dur > xxx amp; dur < xxxx)
#I was thinking to do it this way
сгруппированные два последовательных дня вместе, но возвращают идентификатор группы только один раз, поэтому его нельзя объединить с weather data.frame (я думаю, это проблема). Кроме того, я не уверен, как рассчитать продолжительность для каждых двух последовательных дней, но я думаю, что это можно сделать, как только я смогу сгруппировать последовательные дни вместе.
- Я также подумал об использовании «filter» и «ifelse» для извлечения времени
weather <- weather %>%
filter(
if(diff(Date) <= 1){
Time <= trapstart
}
else{
NULL
}
)
Что-то вроде этого, но это не работает (конечно).
Я действительно хочу создать код примерно так (на самом деле это не код)
weather <- weather %>%
filter(
if("these are two consecutive days"){
"9:45 of the first day < Time <= 9:45 the second day"
}
else{
NULL
}
)
Время записи этого кадра данных не согласуется каждый день, поэтому время записи может отличаться в разные дни, а записанные точки данных отличаются в разные дни.
Вот что я ожидаю от результата (представьте, что у меня есть только 5 записей каждый день):
Date Time DateTime
4/9/2018 9:46 4/9/2018 9:46
4/9/2018 15:34 4/9/2018 15:34
4/9/2018 22:44 4/9/2018 22:44
4/10/2018 4:34 4/10/2018 4:34
4/10/2018 7:09 4/10/2018 7:09
4/10/2018 9:44 4/10/2018 9:44
4/23/2018 9:46 4/23/2018 9:46
4/23/2018 12:27 4/23/2018 12:27
4/23/2018 19:29 4/23/2018 19:29
4/24/2018 1:08 4/24/2018 1:08
4/24/2018 5:24 4/24/2018 5:24
4/24/2018 9:44 4/24/2018 9:44
5/7/2018 9:48 5/7/2018 9:48
5/7/2018 17:59 5/7/2018 17:59
5/8/2018 0:55 5/8/2018 0:55
5/8/2018 1:00 5/8/2018 1:00
5/8/2018 4:30 5/8/2018 4:30
5/8/2018 9:41 5/8/2018 9:41
Я не уверен, что я излагаю свой вопрос понятным образом, поскольку эта логическая вещь сейчас портит мой мозг… Я был бы признателен за любые предложения и помощь! Кроме того, не стесняйтесь просить меня уточнить мой вопрос, если он недостаточно ясен.
Ответ №1:
Я бы использовал dplyr::between
следующим образом.
Во-первых, давайте сгенерируем некоторые образцы данных (всегда лучше явно включать данные вместо предоставления ссылки).
df <- data.frame(
datetime = seq(
as.POSIXct("2018-4-9 00:00"), as.POSIXct("2018-4-11 00:00"), by = "5 min"))
Затем мы можем фильтровать данные между "2018-4-9 9:45"
и "2018-4-9 9:45"
с помощью dplyr::between
library(dplyr)
start <- as.POSIXct("2018-4-9 9:45")
end <- as.POSIXct("2018-4-10 9:45")
df %>% filter(between(datetime, start, end))
PS. Возможно, опечатка, но я думаю, что библиотека, на которую вы ссылаетесь в своем сообщении, называется lubridate
, а не lubricate
.
Обновить
Вы можете добиться фильтрации ваших исходных данных по нескольким (start, end)
диапазонам, используя неравномерное объединение ваших исходных данных df
и фрейма данных, который содержит разные диапазоны.
Вот пример, основанный на приведенных вами образцах данных и используемый fuzzyjoin::fuzzy_inner_join
для выполнения неравновесного соединения:
library(dplyr)
library(fuzzyjoin)
df_range <- data.frame(
start = as.POSIXct(c("2018-4-9 9:45", "2018-4-23 9:45")),
end = as.POSIXct(c("2018-4-10 9:45", "2018-4-24 9:45"))
)
df %>%
fuzzy_inner_join(
df_range,
by = c("datetime" = "start", "datetime" = "end"),
match_fun = list(`>=`, `<=`)) %>%
select(-start, -end)
# datetime
#1 2018-04-09 10:00:00
#2 2018-04-09 11:00:00
#3 2018-04-09 12:00:00
#4 2018-04-09 13:00:00
#5 2018-04-09 14:00:00
#6 2018-04-09 15:00:00
#7 2018-04-09 16:00:00
#8 2018-04-09 17:00:00
#9 2018-04-09 18:00:00
#10 2018-04-09 19:00:00
#11 2018-04-09 20:00:00
#12 2018-04-09 21:00:00
#13 2018-04-09 22:00:00
#14 2018-04-09 23:00:00
#15 2018-04-10 00:00:00
#16 2018-04-23 10:00:00
#17 2018-04-23 11:00:00
#18 2018-04-23 12:00:00
#19 2018-04-23 13:00:00
#20 2018-04-23 14:00:00
#21 2018-04-23 15:00:00
#22 2018-04-23 16:00:00
#23 2018-04-23 17:00:00
#24 2018-04-23 18:00:00
#25 2018-04-23 19:00:00
#26 2018-04-23 20:00:00
#27 2018-04-23 21:00:00
#28 2018-04-23 22:00:00
#29 2018-04-23 23:00:00
#30 2018-04-24 00:00:00
Образец данных
df1 <- data.frame(
datetime = seq(
as.POSIXct("2018-4-9 00:00"), as.POSIXct("2018-4-10 00:00"), by = "60 min"))
df2 <- data.frame(
datetime = seq(
as.POSIXct("2018-4-23 00:00"), as.POSIXct("2018-4-24 00:00"), by = "60 min"))
df3 <- data.frame(
datetime = seq(
as.POSIXct("2018-5-7 00:00"), as.POSIXct("2018-5-8 00:00"), by = "60 min"))
df <- rbind(df1 , df2, df3)
Комментарии:
1. Привет @Maurits Evers, Поскольку у меня более 100 свиданий, есть ли способ сделать это за все эти дни? И спасибо вам за то, что указали на опечатку. Я изменил его.
2. @XM_Z «Поскольку у меня более 100 дат, есть ли способ сделать это со всеми этими днями?» Я не совсем понимаю, что ты имеешь в виду. Можете ли вы отредактировать свой пост, чтобы предоставить более минимальный пример, возможно, на основе примеров данных, которые я даю? Вы хотите отфильтровать исходные данные по нескольким
(start, end)
диапазонам? Если да, пожалуйста, уточните ваш ожидаемый результат.3. Привет @Maurits Evers, я отредактировал свои вопросы в соответствии с рекомендациями. Да, я хотел бы отфильтровать свои исходные данные для более чем одного (начального, конечного) диапазона. У меня есть более 60 групп последовательных дат, и я хотел бы определить эти последовательные даты и отфильтровать период времени (с 9:45 утра первого дня до 9:45 утра следующего дня) среди каждой группы этих последовательных дат, например, 2018-4-9 ~ 2018-4-10, 2018-4-23 ~ 2018-4-24, …., 2020-6-5~2020-6-6.
4. Спасибо за обновление @XM_Z; Я думаю, что вам нужно неравнозначное соединение; Я внес правку в свой пост, пожалуйста, взгляните. Это должно быть легко обобщить для большего количества диапазонов.
5. Спасибо за обновление, @Maurits Evers! Я потрачу некоторое время на обработку данных, чтобы посмотреть, сработает ли это позже сегодня или завтра, и я дам вам знать.