суммирование всех n точек в R
у меня есть вектор, и мне нужно, чтобы сумма всех n numbers и возвращает результаты. Именно так я планирую сделать это сейчас. Есть лучший способ сделать это?
v = 1:100
n = 10
sidx = seq.int(from=1, to=length(v), by=n)
eidx = c((sidx-1)[2:length(sidx)], length(v))
thesum = sapply(1:length(sidx), function(i) sum(v[sidx[i]:eidx[i]]))
Это дает:
thesum
 [1]  55 155 255 355 455 555 655 755 855 955
9 ответов
обновление:
если вы хотите сумме каждые n последовательных чисел использовать colSums
Если вы хотите суммировать каждый nth используйте rowSums
согласно комментарию Джоша, это будет работать только если n делит length(v) красиво. 
rowSums(matrix(v, nrow=n))
 [1] 460 470 480 490 500 510 520 530 540 550
colSums(matrix(v, nrow=n))
 [1]  55 155 255 355 455 555 655 755 855 955
обновление
старая версия не работает. Вот не awnser, который использует rep для создания фактора группировки. Нет необходимости использовать cut:
n <- 5 
vv <- sample(1:1000,100)
seqs <- seq_along(vv)
tapply(vv,rep(seqs,each=n)[seqs],FUN=sum)
можно использовать tapply
tapply(1:100,cut(1:100,10),FUN=sum)
или получить список
by(1:100,cut(1:100,10),FUN=sum)
редактировать
в случае, если у вас есть 1:92, вы можете заменить свой отрезок этого :
cut(1:92,seq(1,92,10),include.lowest=T)
один из способов-преобразовать вектор в матрицу, а затем взять суммы столбцов:
colSums(matrix(v, nrow=n))
[1]  55 155 255 355 455 555 655 755 855 955
просто будьте осторожны: это неявно предполагает, что ваш входной вектор может быть фактически преобразован в матрицу. Если это невозможно, R будет перерабатывать элементы вашего вектора для завершения матрицы.
v <- 1:100
n <- 10
cutpoints <- seq( 1 , length( v ) , by = n )
categories <- findInterval( 1:length( v ) , cutpoints )
tapply( v , categories , sum )
Я добавлю еще один способ сделать это без использования какой-либо функции из apply семья
v <- 1:100
n <- 10
diff(c(0, cumsum(v)[slice.index(v, 1)%%n == 0]))
##  [1]  55 155 255 355 455 555 655 755 855 955
вот некоторые из основных вариантов, предлагаемых до сих пор
f0 <- function(v, n) {
    sidx = seq.int(from=1, to=length(v), by=n)
    eidx = c((sidx-1)[2:length(sidx)], length(v))
    sapply(1:length(sidx), function(i) sum(v[sidx[i]:eidx[i]]))
}
f1 <- function(v, n, na.rm=TRUE) {    # 'tapply'
    unname(tapply(v, (seq_along(v)-1) %/% n, sum, na.rm=na.rm))
}
f2 <- function(v, n, na.rm=TRUE) {    # 'matrix'
    nv <- length(v)
    if (nv %% n)
        v[ceiling(nv / n) * n] <- NA
    colSums(matrix(v, n), na.rm=na.rm)
}
f3 <- function(v, n) {                # 'cumsum'
    nv = length(v)
    i <- c(seq_len(nv %/% n) * n, if (nv %% n) nv else NULL)
    diff(c(0L, cumsum(v)[i]))
}
основные тестовые примеры могут быть
v = list(1:4, 1:5, c(NA, 2:4), integer())
n = 2
f0 не удается с окончательным тестом, но это, вероятно, может быть исправлено
> f0(integer(), n)
Error in sidx[i]:eidx[i] : NA/NaN argument
подход cumsum f3 подвержен ошибке округления, а наличие NA в начале v " яды " более поздние результаты
> f3(c(NA, 2:4), n)
[1] NA NA
С точки зрения производительности, оригинальное решение-это не плохо
> library(rbenchmark)
> cols <- c("test", "elapsed", "relative")
> v <- 1:100; n <- 10
> benchmark(f0(v, n), f1(v, n), f2(v, n), f3(v, n),
+           columns=cols)
      test elapsed relative
1 f0(v, n)   0.012     3.00
2 f1(v, n)   0.065    16.25
3 f2(v, n)   0.004     1.00
4 f3(v, n)   0.004     1.00
но матричное решение f2 кажется быстрым и гибким (например, регулировка обработки этого трейлинг-куска меньше, чем n элементы)
> v <- runif(1e6); n <- 10
> benchmark(f0(v, n), f2(v, n), f3(v, n), columns=cols, replications=10)
      test elapsed relative
1 f0(v, n)   5.804   34.141
2 f2(v, n)   0.170    1.000
3 f3(v, n)   0.251    1.476
один из способов-это использовать rollapply С zoo:
rollapply(v, width=n, FUN=sum, by=n)
# [1]  55 155 255 355 455 555 655 755 855 955
и в случае length(v) не кратен n:
v <- 1:92
rollapply(v, width=n, FUN=sum, by=n, partial=T, align="left")
# [1]  55 155 255 355 455 555 655 755 855 183
немного опоздал на вечеринку, но я не вижу rowsum() ответ. rowsum() доказано, более эффективны, чем tapply() и я думаю, что это также будет очень эффективно по сравнению с некоторыми другими ответами.
rowsum(v, rep(seq_len(length(v)/n), each=n))[,1]
#  1   2   3   4   5   6   7   8   9  10 
# 55 155 255 355 455 555 655 755 855 955
использование метода группировки @Josh O'Brien, вероятно, повысит эффективность еще больше.
rowsum(v, (seq_along(v)-1) %/% n)[,1]
#  0   1   2   3   4   5   6   7   8   9 
# 55 155 255 355 455 555 655 755 855 955 
просто обернуть в unname() чтобы удалить имена групп.  
