У меня есть кадр Data1
данных с тремя колонками: NoContract
, IniDate
, FinDate
представляющий идентификатор контракта, когда начинается договор и при отделки соответственно. С другой стороны, у меня есть период анализа: с 1 января 2012 года по 31 декабря 2014 года. Я хочу найти, сколько контрактов, которые активны в каждом месяце аналитического периода, по активным, я имею в виду, что контракт имеет хотя бы один день от его дат между IniDate
и FinDate
в месяц анализируемого периода.Диапазон дат в период анализа в R
Я пытался в R делать:
Позволяет сказать Data1
является:
Data1 <- data.frame(NoContract= 1:3, IniDate= as.Date(c("2011-05-03","2012-03-13","2014-03-26")),FinDate=as.Date(c("2015-01-05","2013-03-13","2015-08-19")))
Data1
NoContract IniDate FinDate
1 1 2011-05-03 2015-01-05
2 2 2012-03-13 2013-03-13
3 3 2014-03-26 2015-08-19
I've создал еще один кадр данных DatesCalc как:
DatesCalc<-data.frame(monthI=seq(as.Date("2012-01-01"), as.Date("2014-12-31"), by="1 month"), monthF=(seq(as.Date("2012-02-01"), as.Date("2015-01-01"), by="1 month")-1))
head(DatesCalc)
monthI monthF
1 2012-01-01 2012-01-31
2 2012-02-01 2012-02-29
3 2012-03-01 2012-03-31
4 2012-04-01 2012-04-30
5 2012-05-01 2012-05-31
6 2012-06-01 2012-06-30
Далее я написал функцию
myfun<-function(X,Y){
d1<-numeric()
d2<-numeric()
for (i in 1:36){ #36 num of rows on DatesCalc
d1<-numeric()
for (j in 1:3){ #3 num of rows of my Data1 (my actual case near 550K rows)
d1<-c(d1,sum(seq(X[i,1],X[i,2],by=1)%in%seq(Y[j,2],Y[j,3],by=1),na.rm=TRUE)>0)
}
d2<-cbind(d2,d1)
}
return(d2)
}
Итак, что он делает, для каждой строки Data1
создает последовательность дат каждой строки DatesCalc
и доказывает, что это, находится в последовательности дат текущей строки Data1
. Эта функция возвращает матрицу, в которой строки представляют собой контракт и столбцы месяцев с января 2012 года по декабрь 2014 года, и каждая ячейка имеет 1
, если в течение месяца был активен контракт, а 0
, если нет (см. Res
). Наконец, я использовал применить к сумме по столбцу и получил то, что хочу.
Res<-myfun(DatesCalc,Data1)
Res
d1 d1 d1 d1 d1 d1 d1 d1 d1 d1 d1 d1 d1 d1 d1 d1 d1 d1 d1 d1 d1 d1 d1 d1 d1 d1 d1 d1 d1 d1 d1 d1 d1 d1 d1 d1
[1,] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
[2,] 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
[3,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1
apply(Res,2,sum)
d1 d1 d1 d1 d1 d1 d1 d1 d1 d1 d1 d1 d1 d1 d1 d1 d1 d1 d1 d1 d1 d1 d1 d1 d1 d1 d1 d1 d1 d1 d1 d1 d1 d1 d1 d1
1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2
Дело в том, что у меня есть сотни тысяч строк (550K) в моей фактической Data1
, и работает myfun
на ней неэффективно. Мой вопрос, может быть, это способ сделать это эффективным в R? Или любые предложения о том, как улучшить мой код. Спасибо, Comunnity.
Это похоже на случай для 'foverlaps' в' data.table' пакете. Вы найдете очень хорошее Q & A на SO, например. [здесь] (http://stackoverflow.com/questions/27487949/how-to-perform-join-over-date-ranges-using-data-table/27488219#27488219) – Henrik
Спасибо @Henrik Я постараюсь с ' foverlaps' –