2012-09-02 77 views
4

段I有一個data.table和我需要提取相等的長度段開始在不同的行的位置。什麼是最簡單的方法來做到這一點?例如:提取的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中的值不一定是連續的,也不對應於行號。

回答

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子集,然後將它們組合在一起。這比選擇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 
+0

這就是我一直在尋找的!謝謝! – Alex

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 
... 

注意,我首先設置列的鍵,然後創建一個內部data.table加入該列a。創建vec可能不是最好的方法,但這不應該是瓶頸。

+0

我應該讓這個例子更逼真,您的解決方案似乎只是爲了工作,如果data.table簡直是什麼以上。我的值不是1:10,而是真的是2,3,4,293,203,42。我會糾正這個例子 – Alex

+0

@Alex爲什麼你不能只添加一個整數範圍從1到nrow(x)的列? –

+0

是的,這是可能的,但我想避免這樣做,因爲我有一羣羣的,所以我將不得不行號添加到每個組 – Alex