извлечение сегментов данных.стол
У меня есть 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
способ делать вещи, так что я надеялся, что есть лучший способ?
EDIT: в комментариях ниже я редактирую это только для того, чтобы было ясно, что значения в a
не обязательно являются смежными и не соответствуют номеру строки.
2 ответа:
Не уверен, знаете ли вы уже позиции строк или хотите их искать. В любом случае, это должно охватывать и то, и другое.
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: составьте список данных.подмножества таблиц, а затем
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
Я думаю, что это должно быть лучшим способом и в соответствии с 10-минутным введением к данным.таблица, это бинарный поиск и поэтому предпочтительнее:
Обратите внимание, что я сначала задаю столбец a в качестве ключа, а затем создаю внутренние данные.таблица для соединения с этим столбцом a. создание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 ...
vec
, вероятно, не лучший способ, но это не должно быть узким местом.