我的数据集结构如下:
ID origin destination time
1 a b 2
2 b a 1
2 a c 4
3 c b 1
3 b c 3
我想将其转换为ID时间面板数据集,如:
ID location time
1 a 1
1 b 2
1 b 3
1 b 4
2 a 1
2 a 2
2 a 3
2 c 4
3 b 1
3 b 2
3 c 3
3 c 4
所以基本上,我需要在主题不改变位置时创建面板行,并根据原点和目的地的信息填写它们应该位于的位置。 R中是否有任何功能可以顺利完成?我更喜欢使用data.table或dplyr的解决方案。
答案 0 :(得分:4)
您可以为每个time
创建一个表格,以便了解每个location
的{{1}}:
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
(Dplyr还没有滚动或更新联接,所以我猜这里没有模拟。)
工作原理
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
采用某些向量的笛卡尔积,类似于CJ
expand.grid
转换为长格式,将变量保存为melt
id =
在x[i, v := expr]
选择的行上编辑了表v
的列x
i
就地排序setorder
.SD
中的{li> j
是指x[i,j]
选择的数据子集(x
)
i
是滚动联接,其中的行由表x[i, on=, roll=, expr]
,i
和on=
roll=
从x.v
v
关于最后一个项目符号,前缀x
对i.*
中的列执行相同的操作。
答案 1 :(得分:3)
与Frank的解决方案类似的方法,但使用两个连接将是:
library(data.table)
res <- setDT(expand.grid(ID = unique(dt$ID), time = 1:4))
#Get origin
res[dt[,.(ID, origin, time = time - 1L)], location := origin, on = .(ID = ID, time = time)]
#Update origin and destination
res[dt, location := destination, on = c("ID", "time")][, location := zoo::na.locf(location), by = ID][order(ID, time)]
# 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
答案 2 :(得分:3)
我认为你不需要为这个问题进行花哨的连接:
maxt = max(dt$time)
dt[, .(location = c(rep(origin[1], time[1] - 1), rep(destination, diff(c(time, maxt + 1)))),
time = 1:maxt), by = ID]
# ID location time
# 1: 1 a 1
# 2: 1 b 2
# 3: 1 b 3
# 4: 1 b 4
# 5: 2 a 1
# 6: 2 a 2
# 7: 2 a 3
# 8: 2 c 4
# 9: 3 b 1
#10: 3 b 2
#11: 3 c 3
#12: 3 c 4
根据OP示例,我假设在单个ID中,下一个原点与之前的目的地相同。