У меня есть следующая таблица данных (на самом деле таблица содержит гораздо больше наблюдений для большего количества идентификаторов и дат. Кроме того, share1
и share2
на самом деле не всегда одинаковы):
require(data.table)
my.dt <- data.table(id = c(1, 1, 1, 2, 2, 2),
date1 = as.Date(c('2014-01-01', '2014-01-01', '2014-01-05', '2014-01-10', '2014-01-12', '2014-01-20')),
date2 = as.Date(c('2014-01-05', '2014-01-11', '2014-01-07', '2014-01-09', '2014-01-15', '2014-01-22')),
date3 = as.Date(c('2014-01-10', '2014-01-10', '2014-01-13', '2014-01-25', '2014-01-26', '2014-01-27')),
value = c(10, 25, 35, 40, 48, 55),
share1 = 0.4,
share2 = 0.65)
Когда наблюдение достигает date1
, его истинное значение составляет value * share1
. Если оно достигает date2
, его истинное значение равно value * share2
. Если оно достигает date3
, его истинное значение равно нулю. date3
может быть раньше других дат. Если date3
предшествует другим датам, значение остается нулевым. Если date2 < date3 & date2 <= date1
, истинное значение будет value * share2
, пока оно не достигнет date3
.
Я хочу знать для каждого дня, когда что-то происходит (то есть для каждой уникальной даты в таблице. Давайте назовем эту дату b
), каковы доли истинных значений - каждого наблюдения, которое на дату b
уже достигло date1
или date2
, но не достигло date3
- по отношению к их общей сумме дел на данный момент дата b
(для каждого id
). Вот как это должно работать при использовании for-loop
:
# Create empty data table to store loop outcome in
final.table <- data.table()
# Start to loop over id and then dates
for (a in unique(my.dt$id)) {
# Get subset of the data table for the id
my.dt.id <- my.dt[id == a, ]
# Only loop over dates when something is happening
for (b in unique(c(my.dt.id$date1, my.dt.id$date2, my.dt.id$date3))) {
# If date2 <= b take value*share2. If date1 <= b take value*share1. Otherwise, write NA (to be deleted afterwards).
# For all logical statements needs to hold: b < date3
# Also store the id and date
date.cases <- data.table(id = a, date = b, true_value = my.dt.id[b < date3, ifelse(date2 <= b, value * share2,
ifelse(date1 <= b, value * share1, NA))])
# Delete NA values
date.cases <- date.cases[!is.na(true_value), ]
# Calculate share of each case for this date
date.cases[, share := true_value / sum(true_value)]
# Append the date.cases table to the final data table
final.table <- rbind(final.table, date.cases)
}
}
final.table[, date := as.Date(date, origin = as.Date('1970-01-01'))]
Из-за большого количества наблюдений, которые я имею в действительности, это утверждение l oop выполняется очень долго. Поэтому я хотел использовать язык таблиц данных, чтобы получить эту исходящую таблицу намного быстрее. Но я не знаю, как я могу векторизовать это, поскольку мне понадобятся значения keyby
(в этом случае, вероятно, id
и даты) для логических операций для операторов ifelse
. Поэтому мой вопрос - как я могу упростить свой l oop с помощью простой (ых) таблиц данных? Спасибо!