Вы можете составить таблицу с каждым time
, для которого вы хотите знать location
каждого ID
:
newDT = DT[, CJ(ID = unique(ID), time = 1:4)]
Затем поместите исходные данные в длинный формат, выводя, что
- начало координат для
time-1
- пункт назначения сохраняется для
time
mDT = melt(DT, id = c("ID", "time"), value.name = "loc", variable.name = "loc_role")
mDT[loc_role == "origin", time := time - 1L]
mDT[, loc_role := NULL]
setorder(mDT, ID, time)
ID time loc
1: 1 1 a
2: 1 2 b
3: 2 0 b
4: 2 1 a
5: 2 3 a
6: 2 4 c
7: 3 0 c
8: 3 1 b
9: 3 2 b
10: 3 3 c
... и заполните новую таблицу с непрерывным обновлением соединения:
newDT[, location := mDT[.SD, on=.(ID, time), roll=TRUE, x.loc]]
ID time location
1: 1 1 a
2: 1 2 b
3: 1 3 b
4: 1 4 b
5: 2 1 a
6: 2 2 a
7: 2 3 a
8: 2 4 c
9: 3 1 b
10: 3 2 b
11: 3 3 c
12: 3 4 c
(у Dplyr пока нет переходов или обновлений, так что, думаю, аналога нет.)
Как это работает
CJ
принимает декартово произведение некоторых векторов, аналогичное expand.grid
melt
преобразуется в длинную форму, сохраняя переменные, передаваемые как id =
x[i, v := expr]
редактирует столбец v
таблицы x
в строках, выбранных с помощью i
setorder
сортировка на месте
.SD
в j
из x[i,j]
относится к подмножеству данных (x
), выбранному из i
x[i, on=, roll=, expr]
- это скользящее соединение со строками, выбранными таблицей i
, on=
и roll=
- Выражение
x.v
внутри объединения выбирает столбец v
из x
Что касается последнего маркера, префикс i.*
будет делать то же самое для столбцов из i
.