учитывая набор данных, содержащий короткие интервалы, и значение, представляющее среднюю меру чего-либо за каждый интервал, я хотел бы усреднить эти значения до календарного года, отдельно для каждого человека ("id").
Проблема заключается в том, что эти интервалы не совпадают с календарным годом, поэтому для получения наилучшей оценки среднегодового значения по средним значениям более короткого интервала необходимо взвешивание по времени этих значений.
Обратите внимание, чтоинтервалы включают в себя дату начала и исключают дату окончания.
Пример данных
start_date
и end_date
- это уникальные непересекающиеся интервалы в пределах уровней id
:
set.seed(30)
library(lubridate)
library(data.table)
x <- CJ(id=1:5, start_date=seq(from=as.Date("2005-01-12"),by=14,length=100))
#add noise so intervals don't all start on 2005-01-12
x[,start_date:=start_date + rbinom(1,size=20,prob=.15)*15L,by=id]
#all intervals are two weeks:
x[,end_date:=start_date+14]
x[,value:=rnorm(nrow(x))]
#for each id, calculate the mean value over each calendar year.
years <- c(year(min(x$start_date)), year(max(x$start_date)))
Дополнительные ограничения:
- работает для интервалов, длина которых не равна двум неделям
- работает, даже если интервалы не имеют одинаковую длину(до тех пор, пока они не перекрываются)
- работает, даже если самая ранняя дата start_date не одинакова для каждого участника
- averвозраст для календарных лет, для которых этот идентификатор не подходит для завершения года, должен быть NA
Потенциальное решение, которое слишком медленное для моих целей.
complete_date_seq <- seq(as.Date(ymd(paste0(years[1],"-01-01"))), as.Date(ymd(paste0(years[2],"-12-12"))),by=1)
m <- matrix(NA,nrow=length(unique(x$id)),ncol=length(complete_date_seq))
rownames(m) <- unique(x$id)
colnames(m) <- as.character(complete_date_seq)
for(i in 1:nrow(m)){
temp <- x[id==rownames(m)[i]]
for(j in 1:nrow(temp)){
m[i, as.Date(complete_date_seq) %within% temp[j,interval(start_date,end_date-1)]] <- temp[j,value]
}
}
out <- CJ(id=unique(x$id),year=years[1]:years[2])
intervalfromyear <- function(y) interval(as.Date(ymd(paste0(y,"-01-01"))), as.Date(ymd(paste0(y,"-12-31"))))
out[, annual_avg:=mean(m[rownames(m)==.BY$id,complete_date_seq %within% intervalfromyear(.BY$year)]) ,by=c("id","year")]
Я предполагаю, что есть какой-то пакет для взвешивания времени, о котором я не знаю.Это правда?В идеале, есть быстрое решение для работы с данными.