Как рассчитать значения с помощью языка таблиц данных, где для логических операций требуется ключевое значение? - PullRequest
0 голосов
/ 08 апреля 2020

У меня есть следующая таблица данных (на самом деле таблица содержит гораздо больше наблюдений для большего количества идентификаторов и дат. Кроме того, 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 с помощью простой (ых) таблиц данных? Спасибо!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...