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)]
。我做这个笔记,以便稍后更新答案。)
我有两个关于包 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)]
。我做这个笔记,以便稍后更新答案。)