РЕДАКТИРОВАТЬ: , поскольку я совсем не знаком с data.table, есть ли у кого-нибудь идеи для других решений, кроме перехода на data.table?Спасибо огромное!
У меня довольно большой набор данных, который содержит начальные и конечные даты различных типов инцидентов (каждая строка содержит инцидент с соответствующей начальной и конечной датой).Теперь я хотел бы знать, был ли инцидент того же типа непосредственно до или после текущего инцидента.Хитрость заключается в том, что праздники и выходные дни между инцидентами не учитываются / не должны учитываться.
Пример: Инцидент типа 1 начинается в среду, заканчивается в пятницу, затем наступают выходные и понедельник.другой инцидент типа 1 начинается и длится до пятницы.В этом случае «ident_directly_before »будет истинным (= 1) для второго, потому что два инцидента разделены только выходными, что не должно учитываться, и ложным (= 0) для первого, потому что этобыл первым в своем роде.
Я написал функцию для этого, но это довольно медленно.
Теперь у меня вопрос: есть ли у вас идеи, как улучшить производительность кода?
Я читал о предварительном распределении памяти, но, поскольку у меня нет «for (i in 1: n)», я не уверен, как это сделать.
Я также пробовал cmpfun () из пакета компилятора, но он работал более или менее так же (даже немного хуже), чем оригинал.
Поскольку у меня нет фона CS иПросто чтобы углубиться в тему оптимизации кода, я был бы рад получить некоторую помощь, а также объяснить, почему определенные подходы (не) работают в моем случае.
Пакеты:
library(dplyr)
library(lubridate)
Пример данных:
df <- structure(list(start = structure(c(16920, 16961, 16988, 17008, 13563, 13598, 13819, 13880, 13886,
13887, 13892, 13899, 13907, 13910, 13969, 14487, 14488, 14550,
14606, 14676, 14743, 14819, 14841, 14851, 14915, 14984), class = "Date"),
end = structure(c(16927,16965, 16990, 17011, 13595, 13616, 13875, 13885, 13886, 13889,
13896, 13906, 13909, 13966, 13969, 14487, 14496, 14554, 14608,
14680, 14743, 14820, 14841, 14862, 14918, 14985), class = "Date"),
type = c(1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 4, 4, 4, 5, 6, 7, 8, 8, 9, 9, 9, 9, 9, 9)),
class = "data.frame", row.names = c(NA, -26L))
Пример моего пользовательского вектора праздников:
holidays <- as.Date(c("2009-12-30", "2009-12-31", "2010-01-01"))
Моя функция для проверки, еслинезадолго до этого произошел инцидент того же типа (исключая выходные и праздничные дни):
incident_function <- function(startdate, enddate, lagstart, lagend) {
if (is.na(lagstart) ||is.na(lagend) ) {
priorincident <- 0
} else {
daycount <- 0
priorincident <- 0
day_start <- as.Date(startdate) - lubridate::duration(1, 'days')
while (day_start %in% holidays || weekdays(day_start) %in% c("Saturday", "Sunday")) {
daycount <- daycount +1
day_start <- (as.Date(day_start) - lubridate::duration(1, 'days'))
}
{ if (as.Date(day_start) %in% seq.Date(lagstart, lagend, by='days')){
priorincident <- 1
} else {
priorincident <- 0
}
}
return(priorincident)
}
}
Функция в основном делает следующее: 1) если это первый инцидент инцидента типа / лага - NA,присвойте 0 для предварительного инцидента (= не было предшествующего инцидента того же типа).2) иначе: возьмите начальную дату текущей строки и посмотрите, был ли накануне выходной или суббота / воскресенье;если да, вернитесь на один день дальше и проверьте снова (...).Если тогда начальная дата минус n-дней не является ни праздничным днем, ни субботой / воскресеньем, ни конечной датой инцидента с задержкой, присвойте 0 предыдущему инциденту, однако, если начальная дата минус n-дней является конечной датой предыдущего инцидента, назначьте1 to priorincident (= был предшествующий инцидент того же типа).
(аспект "тот же тип" покрыт из-за group_by (type) в трубе dplyr)
Затем я использовал dplyr для группировки по типу инцидента, а затем применил функцию инцидент:
df %>%
group_by(type) %>%
dplyr::mutate(incident_directly_before = mapply(incident_function, startdate=start, enddate=end, lagstart=dplyr::lag(start), lagend=dplyr::lag(end))) -> df
start end type incident_directly_before
<date> <date> <dbl> <dbl>
1 2016-04-29 2016-05-06 1 0
2 2016-06-09 2016-06-13 1 0
3 2016-07-06 2016-07-08 1 0
4 2016-07-26 2016-07-29 1 0
5 2007-02-19 2007-03-23 2 0
6 2007-03-26 2007-04-13 2 1
7 2007-11-02 2007-12-28 2 0
8 2008-01-02 2008-01-07 2 0
9 2008-01-08 2008-01-08 2 1
10 2008-01-09 2008-01-11 2 1
11 2008-01-14 2008-01-18 2 1
12 2008-01-21 2008-01-28 3 0
13 2008-01-29 2008-01-31 4 0
14 2008-02-01 2008-03-28 4 1
15 2008-03-31 2008-03-31 4 1
16 2009-08-31 2009-08-31 5 0
17 2009-09-01 2009-09-09 6 0
18 2009-11-02 2009-11-06 7 0
19 2009-12-28 2009-12-30 8 0
20 2010-03-08 2010-03-12 8 0
21 2010-05-14 2010-05-14 9 0
22 2010-07-29 2010-07-30 9 0
23 2010-08-20 2010-08-20 9 0
24 2010-08-30 2010-09-10 9 0
25 2010-11-02 2010-11-05 9 0
26 2011-01-10 2011-01-11 9 0
Большое спасибо за то, что не позволил мне тратить свою жизнь, уставившись на этот сладкий маленький красный восьмиугольник!