Работать с определенным количеством строк в data.table
Я работаю с таблицей данных, которая имеет группы данных и для каждой позиции (от -1000 до +1000) и подсчет для каждой позиции. Небольшой пример выглядит так:
dt.ex <- data.table(newID=rep(c("A","B"), each = 6), pos=rep(c(-2:3), 2), count= sample(c(1:100), 12))
newID pos count
1: A -2 29
2: A -1 32
3: A 0 33
4: A 1 45
5: A 2 51
6: A 3 26
7: B -2 22
8: B -1 79
9: B 0 2
10: B 1 48
11: B 2 87
12: B 3 38
Что я хочу сделать, это рассчитать среднее (или сумму) между каждыми n строками для каждой группы newID. То есть разбить на n строк и агрегировать результаты. Это будет вывод при условии n=3 и суммировании:
newID pos count
A -2 94
A 1 122
B -2 103
B 1 173
И я, честно говоря, понятия не имею, с чего начать, не прибегая к каким-либо циклам - не рекомендуется для таблицы 67094000 x 3. Если бы я хотел рассчитывать только по новым идентификаторам, что-то вроде этого помогло бы, но я еще не нашел решение, которое было бы близко к ответу на мой вопрос. Решения Plyr также приветствуются, хотя я чувствую, что это может быть слишком медленным для этого.
2 ответа
Альтернативный способ (без использования .SD
) было бы:
dt.ex[, seq := (seq_len(.N)-1) %/% 3, by=newID][,
list(pos = mean(pos), count=sum(count)), list(newID, seq)]
Сравнительный анализ (относительно) больших данных:
set.seed(45)
get_grps <- function() paste(sample(letters, 5, TRUE), collapse="")
grps <- unique(replicate(1e4, get_grps()))
dt.in <- data.table(newID = sample(grps, 6e6, TRUE),
pos = sample(-1000:1000, 6e6, TRUE),
count = runif(6e6))
setkey(dt.in, newID)
require(microbenchmark)
eddi <- function(dt) {
dt[, .SD[, list(pos = mean(pos), count = sum(count)),
by = seq(0, .N-1) %/% 3], by = newID]
}
arun <- function(dt) {
dt[, seq := (seq_len(.N)-1) %/% 3, by=newID][,
list(pos = mean(pos), count=sum(count)), list(newID, seq)]
}
microbenchmark(o1 <- eddi(copy(dt.in)), o2 <- arun(copy(dt.in)), times=2)
Unit: seconds
expr min lq median uq max neval
o1 <- eddi(copy(dt.in)) 25.23282 25.23282 26.16009 27.08736 27.08736 2
o2 <- arun(copy(dt.in)) 13.59597 13.59597 14.41190 15.22783 15.22783 2
Попробуй это:
dt.ex[, .SD[, list(pos = mean(pos), count = sum(count)),
by = seq(0, .N-1) %/% 3],
by = newID]
Обратите внимание, что родитель data.table
"s .N
используется во вложенных by
, так как .N
существует только в j-expression
,