【问题标题】:How do I create a panel dataset out of transition date data in R?如何使用 R 中的转换日期数据创建面板数据集?
【发布时间】:2018-04-30 14:39:03
【问题描述】:

我有一个结构如下的数据集:

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 的解决方案。

【问题讨论】:

  • 你可以查看zoo::na.locf
  • 您要扔掉,例如,ID 2 最初位于 b 的信息?
  • @Frank 不。我不想把它扔掉。这只是我的一个考虑不周的示例数据。
  • 输入示例似乎很难处理。例如,我们是否应该假设如果在时间 = 1 时没有观察,它们从 a 开始?

标签: r dplyr data.table


【解决方案1】:

你可以用你想知道每个locationtime的每个time做一个表:

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]i 选择的行上编辑表x 的列v
  • setorder 排序到位
  • .SD in j of x[i,j] 指的是由i 选择的数据子集(x
  • x[i, on=, roll=, expr] 是一个滚动连接,行由表ion=roll= 选择
  • 连接内的表达式x.vx 中选择列v

关于最后一个项目符号,前缀 i.* 将对来自 i 的列执行相同的操作。

【讨论】:

    【解决方案2】:

    与 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
    

    【讨论】:

      【解决方案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 中,下一个起点与上一个目的地相同。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-02-02
        • 2018-07-05
        • 2021-03-24
        • 1970-01-01
        • 1970-01-01
        • 2015-05-13
        • 2021-11-18
        • 2017-10-16
        相关资源
        最近更新 更多