我有两个关于' by'在包data.table。
中 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
现在我玩了.I
的data.table,并没有给我任何我想要的东西:我(:-)抱歉,无法抗拒)预计会工作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)执行&#39;语句
是正确的方式,还是可以“走私”进入&#39; SQL&#39; ORDER BY&#39;某处?
例如:如果我们从上面反转数据表
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]
但是有没有正确的&#39;这样做的方式?即是否保证订单在执行by-statement时保持固定?
谢谢: - )
FW
答案 0 :(得分:4)
.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)]
。我正在编写此笔记,以便稍后更新答案。)