r data.table:关于'by'的两个问题((1)=.I and (2)='order by')

r data.table: two questions about 'by' ((1)=.I and (2)='order by')

我有两个关于包 data.table 中的 'by' 的问题。

1) 如何与.I一起使用呢?例如,假设我们有用户在一天中的特定时间进入商店,我想要一个变量告诉我“我们看到这个用户的时间是多少?”......即

> library(data.table)
> dt = data.table(visitorId = c(1,2,1,2,1), daytime=c(1,4,7,9,11))
> dt
       visitorId daytime
1:         1        1
2:         2        4
3:         1        7
4:         2        9
5:         1       11

所需的解决方案会产生

       visitorId daytime  howOftenHaveYouBeenHere
1:         1        1              1
2:         2        4              1
3:         1        7              2
4:         2        9              2
5:         1       11              3

现在我玩弄了 data.table 的 .I 并没有给我想要的东西:我 (:-) 抱歉,无法抗拒)期望工作的东西是 dt = dt[, howOftenHaveYouBeenHere := .I, by=visitorId] 但这给出了

       visitorId daytime  howOftenHaveYouBeenHere
1:         1        1              1
2:         2        4              1
3:         1        7              2
4:         2        9              2
5:         1       11              1 <---- not a 3 here!!!

我使用

让它工作
dt = dt[, stupid := 1]
dt = dt[, session := cumsum(stupid), by=visitorId]; print(dt)

但是这样做感觉不太好...

2) 如何确保 data.table 按 'time' 计算会话数,即直到现在我才

a) 相应地订购 table

b) 执行'by'语句

这是正确的方法还是 'smuggle in' SQL 的 'ORDER BY' 可以在某个地方?

例如:如果我们从上面反转数据table dt = data.table(visitorId = c(1,2,1,2,1), daytime=c(11,9,7,4,1)) 然后

dt = dt[, stupid := 1]
dt = dt[, session := cumsum(stupid), by=visitorId]; print(dt)

没有给出想要的结果。我们可以像这样修复它:

dt = data.table(visitorId = c(1,2,2,1,1), dayTime=c(11,9,4,7,1))
dt = dt[order(dayTime, decreasing=FALSE)]
dt = dt[, stupid := 1]
dt = dt[, howOftenHaveYouBeenHere := cumsum(stupid), by=visitorId]

但是有 'correct' 的方法吗? IE。是否保证在执行 by-statement 时顺序保持不变?

谢谢 :-)

转发

.I 是整个 table 中的计数器——而不是按组。我们需要构建一个组内计数器:

dt[, seqobs := seq_along(.I), by=visitorId]
# or...
dt[, seqobs := seq_len(.N), by=visitorId]
# or...
dt[, seqobs := 1:.N, by=visitorId]

#    visitorId daytime seqobs
# 1:         1       1      1
# 2:         2       4      1
# 3:         1       7      2
# 4:         2       9      2
# 5:         1      11      3

这比初始化一列 1 并取累计和更容易。


每个组中的数据需要按 daytime 排序,这样才有意义。如果不是...

# example of an out-of-order table
dt2 <- dt[sample(.N)]

dt2[order(daytime), seqobs := seq(.N), by=visitorId]

顺便说一句,如果你想改变data.table的顺序,使用setorder函数。

(在data.table包的下一个版本1.9.8中,会有一个小快捷方式dt[, seqobs := rowidv(visitorId)]。我做这个笔记,以便稍后更新答案。)