Применение функции к последовательным субвекторам одинакового размера - PullRequest
4 голосов
/ 14 сентября 2011

Я ищу хороший и быстрый способ применения некоторой произвольной функции, которая работает с векторами, например, sum, последовательно к подвектору последовательных K элементов.Вот один простой пример, который должен очень четко проиллюстрировать то, что я хочу:

v <- c(1, 2, 3, 4, 5, 6, 7, 8)
v2 <- myapply(v, sum, group_size=3) # v2 should be equal to c(6, 15, 15)

Функция должна попытаться обработать группы из group_size элементов данного вектора и применить функцию к каждой группе (обрабатывая еекак еще один вектор).В этом примере вектор v2 получается следующим образом: (1 + 2 + 3) = 6, (4 + 5 + 6) = 15, (7 + 8) = 15. В этом случае K неразделите N точно, поэтому последняя группа имела размер меньше K.

Если есть более хорошее / быстрое решение, которое работает, только если N кратно K, я также был бы признателен за это.

Ответы [ 3 ]

7 голосов
/ 14 сентября 2011

Попробуйте это:

library(zoo)
rollapply(v, 3, by = 3, sum, partial = TRUE, align = "left")
## [1]  6 15 15

или

apply(matrix(c(v, rep(NA, 3 - length(v) %% 3)), 3), 2, sum, na.rm = TRUE)
## [1]  6 15 15

Кроме того, в случае sum последний может быть сокращен до

colSums(matrix(c(v, rep(0, 3 - length(v) %% 3)), 3))
2 голосов
/ 14 сентября 2011

Как сказал @Chase в комментарии, вы можете создать свою собственную переменную группировки и затем использовать ее.Оборачивание этого процесса в функцию будет выглядеть как

myapply <- function(v, fun, group_size=1) {
    unname(tapply(v, (seq_along(v)-1) %/% group_size, fun))
}

, что дает ваши результаты

> myapply(v, sum, group_size=3)
[1]  6 15 15

Обратите внимание: для этого не требуется, чтобы длина v была кратна group_size.

0 голосов
/ 26 августа 2013

Вы можете попробовать это тоже.Это хорошо работает, даже если вы хотите включить перекрывающиеся интервалы, которые контролируются by, и в качестве бонуса возвращает интервалы, по которым выводится каждое значение:

library (gtools)
v2 <- running(v, fun=sum, width=3, align="left", allow.fewer=TRUE, by=3)

v2
1:3 4:6 7:8 
  6  15  15 
...