【问题标题】:r data.table: two questions about 'by' ((1)=.I and (2)='order by')r data.table:关于'by'的两个问题((1)=.I和(2)='order by')
【发布时间】:2015-07-02 14:29:49
【问题描述】:

我对包 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 按“时间”计算会话数,即直到现在我都这样做了

a) 相应地对表格进行排序

b) 执行'by'语句

这是正确的方式还是可以在某处“偷运”SQL 的“ORDER BY”?

例如:如果我们从上面反转数据表 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]

但是有没有“正确”的方法呢? IE。执行副语句时是否保证订单保持不变?

谢谢:-)

FW

【问题讨论】:

  • 抱歉,在玩您的解决方案时感到困惑并陷入困境 :-) 现在清楚了吗?
  • 是的,有道理。谢谢

标签: r data.table


【解决方案1】:

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

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

这比初始化一列并获取累积和要容易。


需要在每个组中按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)]。我正在做这个记录,以便稍后更新答案。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-19
    • 2017-02-11
    • 2011-06-28
    相关资源
    最近更新 更多