У меня есть большая таблица данных (около 900 тыс. Строк), которую можно представить в следующем примере:
row.id entity.id event.date result
1: 1 100 2015-01-20 NA
2: 2 101 2015-01-20 NA
3: 3 104 2015-01-20 NA
4: 4 107 2015-01-20 NA
5: 5 103 2015-01-23 NA
6: 6 109 2015-01-23 NA
7: 7 102 2015-01-23 NA
8: 8 101 2015-01-26 NA
9: 9 110 2015-01-26 NA
10: 10 112 2015-01-26 NA
11: 11 109 2015-01-26 NA
12: 12 130 2015-01-29 NA
13: 13 100 2015-01-29 NA
14: 14 127 2015-01-29 NA
15: 15 101 2015-01-29 NA
16: 16 119 2015-01-29 NA
17: 17 104 2015-02-03 NA
18: 18 101 2015-02-03 NA
19: 19 125 2015-02-03 NA
20: 20 130 2015-02-03 NA
По существу, у меня есть столбцы, содержащие: идентификатор, представляющий рассматриваемый объект (entity.id).);дата события, в котором участвовал этот идентификатор (обратите внимание, что в каждом событии будет участвовать много разных организаций).Мне нужно рассчитать коэффициент, который для каждого entity.id на каждую дату события зависит (нелинейно) от времени (в днях), которое прошло с момента всех предыдущих событий, в которые был введен этот идентификатор объекта.
Чтобы выразить это другими, более программными терминами, в каждой строке таблицы данных. Мне нужно найти все экземпляры с совпадающим идентификатором, где дата старше, чем дата события рассматриваемой строки, работаетвыведите разницу во времени (в днях) между «текущими» и историческими событиями и суммируйте некоторую нелинейную функцию, примененную к каждому из периодов времени (в этом примере я буду использовать квадрат).
В приведенном выше примере для entity.id = 101 03-02-2015 (строка 18) нам нужно будет вернуться к предыдущим записям этого идентификатора в строках 15, 8 и 2, рассчитать разницу в днях от 'текущее событие (14, 8 и 5 дней), а затем вычислите ответ суммированием квадратов этих периодов (14 ^ 2 + 8 ^ 2 + 5 ^ 2) = 196 + 64 + 25 = 285. (Действительная функциянесколько сложнее, но это достаточно представительно.)
Это тривиально для достижения с помощью циклов for, как показано ниже:
# Create sample dt
dt <- data.table(row.id = 1:20,
entity.id = c(100, 101, 104, 107, 103, 109, 102, 101, 110, 112,
109, 130, 100, 127, 101, 119, 104, 101, 125, 130),
event.date = as.Date(c("2015-01-20", "2015-01-20", "2015-01-20", "2015-01-20",
"2015-01-23", "2015-01-23", "2015-01-23",
"2015-01-26", "2015-01-26", "2015-01-26", "2015-01-26",
"2015-01-29", "2015-01-29", "2015-01-29", "2015-01-29", "2015-01-29",
"2015-02-03", "2015-02-03", "2015-02-03", "2015-02-03")),
result = NA)
setkey(dt, row.id)
for (i in 1:nrow(dt)) { #loop through each entry
# get a subset of dt comprised of rows with this row's entity.id, which occur prior to this row
event.history <- dt[row.id < i & entity.id == entity.id[i]]
# calc the sum of the differences between the current row event date and the prior events dates, contained within event.history, squared
dt$result[i] <- sum( (as.numeric(dt$event.date[i]) - as.numeric(event.history$event.date)) ^2 )
}
К сожалению, на реальном наборе данных это также чрезвычайномедленно, без сомнения, потому чтое, если количество операций поднабора требуется.Есть ли способ векторизации или ускорения этой операции?Я искал, искал и искал свои мозги, но не могу понять, как произвольно подбирать строки на основе разных данных для каждой строки без зацикливания.
Обратите внимание, что я создал столбец row.id, чтобы позволить мнеизвлекать все предыдущие строки (а не предыдущие даты), так как они в целом эквивалентны (организация не может посещать более одного события в день), и этот способ был намного быстрее (я думаю, потому что он избегает необходимости приводить даты к числовым значениям доделать сравнение, т. е. Dt [as.numeric (event_date)
Обратите внимание, что я не предан тому, чтобы быть data.table;с удовольствием используйте dplyr или другие механизмы для достижения этой цели, если это будет необходимо.