У меня есть один data.frame с событиями и временными метками их прибытия (с точностью до микросекунды). Во втором кадре данных у меня есть состояния с начальным и конечным временем (= интервал действия).
Ниже я написал для цикла цикла, который делает работу, но действительно медленно . Я думаю, что сочетание data.table, map / apply, распараллеливания (у меня доступно 12 ядер) может существенно сократить время обработки.
Не могли бы вы помочь оптимизировать мой код?
Спасибо!
options(digits.secs = 6)
start <- strptime("2019-10-16 08:00:00.789543 CET", "%Y-%m-%d %H:%M:%OS")
start <- format(start, "%Y-%m-%d %H:%M:%OS")
end <- strptime("2019-10-16 08:10:00.471123 CET", "%Y-%m-%d %H:%M:%OS")
end <- format(end, "%Y-%m-%d %H:%M:%OS")
#### events
event_timestamps <- seq.POSIXt(as.POSIXct(start),
as.POSIXct(end), units = "seconds", by = .1)
events <- sprintf("event%s",seq(1:length(event_timestamps)))
events_df <- data.frame(event_timestamps, events, stringsAsFactors=FALSE)
#### states
states <- sprintf("state%s",seq(1:4))
state_start <- c("2019-10-16 07:00:00.000000 CEST",
"2019-10-16 08:03:00.765233 CEST",
"2019-10-16 08:05:03.765432 CEST",
"2019-10-16 08:05:03.765434")
state_end <- c("2019-10-16 08:03:00.765232 CEST",
"2019-10-16 08:05:03.765431 CEST",
"2019-10-16 08:05:03.765433 CEST",
"2019-10-16 08:12:03.471122 CEST")
states_df <- data.frame(states, state_start = as.POSIXct(state_start),
state_end = as.POSIXct(state_end), stringsAsFactors=FALSE)
#The state dataframe contains states with non-overlapping start and end timestamps.
#That means that one event can fall into exactly one state
# the goal is for every event to find the state it belongs to
#########################################################################
library(lubridate)
# empty data.frame
resulting_df <- data.frame(events = character(),
state = character(),
stringsAsFactors=FALSE)
# loop eventy by event
for(event in 1:nrow(events_df)) {
# go with the event to the states data.frame
for (state in 1:nrow(states_df)) {
# define state's interval
interv <- lubridate::interval(states_df$state_start[state], states_df$state_end[state], tzone = 'CET')
# check for every event if its timestamp is within the state interval
if (events_df$event_timestamps[event] %within% interv){
# then write the temp data.frame
temp <- data.frame(events = events_df$events[event],
state = states_df$states[state],
stringsAsFactors=FALSE)
# collect events with states
resulting_df <- dplyr::bind_rows(resulting_df, temp)
rm(temp)
# one event can only be in one state at a time
# after we found the state for the event, break the inner state loop
# and move to the next event
break
next
}
}
}