【问题标题】:Lagged lists in data.table R [duplicate]data.table R中的滞后列表[重复]
【发布时间】:2016-07-02 14:52:52
【问题描述】:

Rdata.table 中的shift 非常适合时间序列和时间窗口的内容。但是列表的列不会像其他元素的列那样滞后。在下面的代码中,gearLag 领先/滞后gear 正确,但gearsListLag 没有滞后gearsList,相反,shiftgearsList 内运行以滞后同一行中的元素自身。

dt <- data.table(mtcars)[,.(gear, carb, cyl)]
###  Make col of lists
dt[,carbList:=list(list(unique(carb))), by=.(cyl, gear)]
###  Now I want to lag/lead col of lists
dt[,.(carb, carbLag=shift(carb)
    , carbList, carbListLag=shift(carbList, type="lead")), by=cyl] 

    cyl carb carbLag carbList carbListLag
 1:   6    4      NA         4           NA
 2:   6    4       4         4           NA
 3:   6    1       4         1           NA <-- should be 4 here, not NA
 4:   6    1       1         1           NA
 5:   6    4       1         4           NA
 6:   6    4       4         4           NA
 7:   6    6       4         6           NA
 8:   4    1      NA       1,2         2,NA
 9:   4    2       1       1,2         2,NA
10:   4    2       2       1,2         2,NA
11:   4    1       2       1,2         2,NA
12:   4    2       1       1,2         2,NA
13:   4    1       2       1,2         2,NA
14:   4    1       1         1           NA <-- should be (1,2) here, not NA
15:   4    1       1       1,2         2,NA
16:   4    2       1         2           NA
17:   4    2       2         2           NA
18:   4    2       2       1,2         2,NA
19:   8    2      NA     2,4,3      4, 3,NA
20:   8    4       2     2,4,3      4, 3,NA
21:   8    3       4     2,4,3      4, 3,NA
22:   8    3       3     2,4,3      4, 3,NA
23:   8    3       3     2,4,3      4, 3,NA

有什么建议可以像我在其他元素上滞后一样滞后于列表吗?

【问题讨论】:

  • shift 似乎不支持列表。试试shift(list(list(1,2), list(3,4))) # Error Unsupported type 'list'。您可以从您看到的结果中看出它正在迭代列表并将shift 分别应用于每个元素,这与您shift(.SD) 时发生的情况一致(每列是一个列表元素,分别移动)。
  • 您可能想在github page 上提出问题,以便更轻松地处理此问题
  • better solution was recently implemented 以来将其作为 dup 关闭。
  • @enfastication,我注意到您是最初提出问题的人。再次感谢。

标签: r list data.table lag


【解决方案1】:

这是记录在案的行为。这是?shift 的示例的一部分:

# on lists
ll = list(1:3, letters[4:1], runif(2))
shift(ll, 1, type="lead")
# [[1]]
# [1]  2  3 NA
# 
# [[2]]
# [1] "c" "b" "a" NA 
# 
# [[3]]
# [1] 0.1190792        NA

要解决这个问题,您可以为列表的每个值创建一个唯一 ID:

dt[, carbList_id := match(carbList, unique(carbList))]

carbList_map = dt[, .(carbList = list(carbList[[1]])), by=carbList_id]

#    carbList_id carbList
# 1:           1        4
# 2:           2      1,2
# 3:           3        1
# 4:           4    2,4,3
# 5:           5        2
# 6:           6      4,8
# 7:           7        6

# or stick with long-form:
carbList_map = dt[, .(carb = carbList[[1]]), by=carbList_id]

#     carbList_id carb
#  1:           1    4
#  2:           2    1
#  3:           2    2
#  4:           3    1
#  5:           4    2
#  6:           4    4
#  7:           4    3
#  8:           5    2
#  9:           6    4
# 10:           6    8
# 11:           7    6

然后,只需 shift 或带有新 ID 列的任何内容。当您再次需要carbList 的值时,您必须与新表合并。

或者,如果您真的不需要处理这些值,而只是为了浏览它们,请考虑将其改为字符串,例如carbList:=toString(sort(unique(carb)))paste0

旁注:在使用toStringpaste0list 之前进行排序。

【讨论】:

    【解决方案2】:

    用户 Frank 指出 shift 不支持列表。这是forset 的解决方案,它使用data.table 计算组内滞后的正确指数,但在for 中完成所有其他工作。除了一些小的优化,这是我在data.table 中所希望的最好的(干净+快速)吗?

    dt <- data.table(mtcars)[,.(gear, carb, cyl)]
    dt[,carbsList:=list(list(unique(carb))), by=.(cyl, gear)]
    dt[,':='(rowLag=shift(.I), gearLag=shift(gear)), by=cyl]
    dt[,':='(carbsListLag=list())]
    cl_j <- which(names(dt) == "carbsListLag")
    for (i in 1:nrow(dt)) {
       set(dt, i, cl_j, dt[dt[i,rowLag], list(carbsList)])
    }
    dt[,.(carb, gear, gearLag, carbsList, carbsListLag, .I, rowLag), by=cyl]
        cyl carb gear gearLag carbsList carbsListLag  I rowLag
     1:   6    4    4      NA         4         NULL  1     NA
     2:   6    4    4       4         4            4  2      1
     3:   6    1    3       4         1            4  4      2
     4:   6    1    3       3         1            1  6      4
    ...
    13:   4    1    4       4       1,2          1,2 20     19
    14:   4    1    3       4         1          1,2 21     20
    15:   4    1    4       3       1,2            1 26     21
    16:   4    2    5       4         2          1,2 27     26
    17:   4    2    5       5         2            2 28     27
    18:   4    2    4       5       1,2            2 32     28
    19:   8    2    3      NA     2,4,3         NULL  5     NA
    20:   8    4    3       3     2,4,3        2,4,3  7      5
    

    【讨论】:

    • set 的第三个参数可以是列名,例如“carbsListLag”而不是数字,您的 c1_j。另外,我猜你的:= 可以一步而不是两步..?最后,可能需要NA 代替NULL(我不确定)。
    猜你喜欢
    • 1970-01-01
    • 2020-11-16
    • 2012-07-09
    • 1970-01-01
    • 2012-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多