我有一个data.table
,我需要从不同的行位置开始提取相等长度的段。最简单的方法是什么?例如:
x <- data.table(a=sample(1:1000,100), b=sample(1:1000,100))
r <- c(1,2,10,20,44)
idx <- lapply(r, function(i) {j <-which(x$a == i); if (length(j)>0) {return(j)} })
y <- lapply(idx, function(i) {if (!is.null(i)) x[i:(i+5)]})
do.call(rbind, y)
a b
1: 44 63
2: 96 730
3: 901 617
4: 446 370
5: 195 341
6: 298 411
这肯定不是data.table
做事的方式所以我希望有更好的方法吗?
编辑:根据下面的评论,我编辑它只是为了清楚a
中的值不一定是连续的,也不对应于行号。
答案 0 :(得分:6)
不确定您是否已知道行位置,或者是否要搜索行位置。无论哪种方式,这应该涵盖两者。
require(data.table)
set.seed(1)
DT = data.table(a=sample(1:1000,20), b=sample(1:1000,20))
setkey(DT,a)
DT
# a b
# 1: 62 338
# 2: 175 593
# 3: 201 267
# 4: 204 478
# 5: 266 935
# 6: 372 212
# 7: 374 711
# 8: 380 184
# 9: 491 659
# 10: 572 651
# 11: 625 863
# 12: 657 380
# 13: 679 488
# 14: 707 782
# 15: 760 816
# 16: 763 404
# 17: 894 385
# 18: 906 126
# 19: 940 14
# 20: 976 107
r = c(201,380,760)
starts = DT[J(r),which=TRUE] # binary search for items
# skip if the starting row numbers are known
starts
# [1] 3 8 15
选项1:制作行号序列,连接并在DT
中执行一次查找(不需要键或二进制搜索只需按行号选择):
DT[unlist(lapply(starts,seq.int,length=5))]
# a b
# 1: 201 267
# 2: 204 478
# 3: 266 935
# 4: 372 212
# 5: 374 711
# 6: 380 184
# 7: 491 659
# 8: 572 651
# 9: 625 863
# 10: 657 380
# 11: 760 816
# 12: 763 404
# 13: 894 385
# 14: 906 126
# 15: 940 14
选项2:制作一个data.table子集列表,然后将rbind
组合在一起。这比选项1效率低,但是为了完整性:
L = lapply(starts,function(i)DT[seq.int(i,i+4)])
L
# [[1]]
# a b
# 1: 201 267
# 2: 204 478
# 3: 266 935
# 4: 372 212
# 5: 374 711
#
# [[2]]
# a b
# 1: 380 184
# 2: 491 659
# 3: 572 651
# 4: 625 863
# 5: 657 380
#
# [[3]]
# a b
# 1: 760 816
# 2: 763 404
# 3: 894 385
# 4: 906 126
# 5: 940 14
rbindlist(L) # more efficient that do.call("rbind",L). See ?rbindlist.
# a b
# 1: 201 267
# 2: 204 478
# 3: 266 935
# 4: 372 212
# 5: 374 711
# 6: 380 184
# 7: 491 659
# 8: 572 651
# 9: 625 863
# 10: 657 380
# 11: 760 816
# 12: 763 404
# 13: 894 385
# 14: 906 126
# 15: 940 14
答案 1 :(得分:1)
我认为这应该是一种更好的方法,根据10 minute introduction到data.table,这是一个二元搜索,因此更可取:
library(data.table)
x <- data.table(a=1:100, b=1:100, key="a")
r <- c(1,2,10,20,44)
vec <- numeric()
for (elem in r) {
vec <- c(vec, seq(from=elem, by=1, length.out=6))
}
x[data.table(vec)]
a b
1: 1 1
2: 2 2
3: 3 3
4: 4 4
5: 5 5
6: 6 6
7: 2 2
...
请注意,我首先将列a设置为键,然后创建一个内部data.table以与该列连接。 vec
的创建可能不是最好的方法,但这不应该成为瓶颈。