21

ベクトルがあり、すべてnの数値を合計して結果を返す必要があります。これは私が現在それを行うことを計画している方法です。これを行うためのより良い方法はありますか?

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
4

9 に答える 9

31
unname(tapply(v, (seq_along(v)-1) %/% n, sum))
# [1] 55 155 255 355 455 555 655 755 855 955 
于 2013-03-07T07:39:08.137 に答える
20

アップデート:

n個の連続する数字ごとに合計するcolSums
場合は次を使用しますn番目ごとの数字を合計する場合rowSums

Joshのコメントによると、これはうまく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

于 2013-03-07T07:48:42.573 に答える
13

アップデート

古いバージョンは機能しません。repここでは、グループ化係数を作成するために使用する新しいawnserです。使用する必要はありません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)
于 2013-03-07T07:38:33.113 に答える
7

1つの方法は、ベクトルを行列に変換してから、列の合計を取得することです。

colSums(matrix(v, nrow=n))
[1]  55 155 255 355 455 555 655 755 855 955

注意してください。これは、入力ベクトルが実際に行列に再形成できることを暗黙的に想定しています。できない場合、Rはベクトルの要素をリサイクルしてマトリックスを完成させます。

于 2013-03-07T07:43:25.857 に答える
4
v <- 1:100

n <- 10

cutpoints <- seq( 1 , length( v ) , by = n )

categories <- findInterval( 1:length( v ) , cutpoints )

tapply( v , categories , sum )
于 2013-03-07T07:39:31.117 に答える
3

apply家族の機能なしでそれを行うもう1つの方法を追加します

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
于 2013-03-07T08:00:17.537 に答える
2

これまでに提供された主なバリエーションのいくつかを次に示します

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は丸め誤差の影響を受けやすく、 v「毒」の初期のNAの存在は後の結果になります

> 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
于 2013-03-07T18:30:46.850 に答える
2

1つの方法は、次から使用すること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
于 2017-05-14T13:50:08.470 に答える
2

パーティーに少し遅れましたが、まだ答えがわかり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()グループ名を削除するには、 ラップインするだけです。

于 2017-10-31T22:40:17.917 に答える