在矢量不同长度的滚动总和

时间:2015-07-06 17:55:50

标签: r

说我有一个矢量:

l1

对于不同的整数l2我想要向量的k个连续元素的总和,即我对k = 1的期望输出是向量本身

Public Sub break_data()

Dim row As Integer: row = 500      'Number of rows to read on a column

Dim wks As Object                  'Source Sheet
Set wks = ThisWorkbook.Sheets("Sheet1")

Dim wkr As Object                  'Result Sheet
Set wkr = ThisWorkbook.Sheets("Sheet2")

Dim i As Integer: i = 1
Dim j As Integer: j = 1             'Column that you want to split

Dim x As Integer: x = 1
Dim y As Integer: y = 1

Do While (i <= 500)
    If (Len(Trim(wks.Cells(i, j).Value)) > 0) Then
        wkr.Cells(x, y).Value = wks.Cells(i, j).Value
        x = x + 1
    ElseIf (Len(Trim(wks.Cells(i, j).Value)) = 0) And (x <> 1) Then
        x = 1
        y = y + 1
    End If
    i = i + 1
Loop
End Sub

并且对于k = 2:

vec = 1:10
vec
[1]  1  2  3  4  5  6  7  8  9 10

依此类推 - 在这个例子中,k = 10是我想要的最后一个:

k

即。我向量的所有10个条目的总和。

在我的实际数据[1] 1 2 3 4 5 6 7 8 9 10 中,长度为~10 ^ 6,[1] 3 5 7 9 11 13 15 17 19 ,条目为有符号实数。

编辑: 我对性能感到好奇所以我做了我的第一个基准测试:

[1] 55

我测试了部分实际数据和较小的vec(对于较大的k=1:1000,所有algos因RAM问题而减速)。 Khashaa的算法是明显的赢家,并且还能够处理NAs。但是,根据akrun和mra68建议的答案,这可以通过> library(RcppRoll) > library(zoo) > library(microbenchmark) > > f <- Vectorize(function(x, k)RcppRoll::roll_sum(x, k), vectorize.args = "k") > out = list() > vec = na.omit(myrealdata) > vec = vec[1:1e4] > mb = microbenchmark(Khashaa = f(vec, 1:100), + mra68 = for(k in (1:100)){out[[k]] <- k*rollmean(vec, k)}, + akrun = sapply(1:100, function(x) rollsum(vec, k=x)), times = 100) > print(mb) Unit: milliseconds expr min lq mean median uq max neval Khashaa 48.12953 49.08398 49.89553 49.55445 50.27705 53.23208 100 mra68 557.93112 564.74246 578.07404 568.95936 576.81239 858.52096 100 akrun 549.48471 556.68814 570.50853 560.17078 565.31508 1190.12545 100 来完成。谢谢你的答案!

2 个答案:

答案 0 :(得分:6)

尝试

x <- 1:10
k <- 1:10
f <- Vectorize(function(x, k)RcppRoll::roll_sum(x, k),  vectorize.args = "k")
f(x, k)


[[1]]
 [1]  1  2  3  4  5  6  7  8  9 10

[[2]]
[1]  3  5  7  9 11 13 15 17 19

[[3]]
[1]  6  9 12 15 18 21 24 27

[[4]]
[1] 10 14 18 22 26 30 34

[[5]]
[1] 15 20 25 30 35 40

[[6]]
[1] 21 27 33 39 45

[[7]]
[1] 28 35 42 49

[[8]]
[1] 36 44 52

[[9]]
[1] 45 54

[[10]]
[1] 55

答案 1 :(得分:2)

由于平均值和总和密切相关,我们也可以使用&#39; rollmean&#39;来自动物园的功能&#39;包:

vec <- 1:10
for ( k in (1:10) ) { print(k*rollmean(vec,k)) }

根据需要输出:

[1]  1  2  3  4  5  6  7  8  9 10
[1]  3  5  7  9 11 13 15 17 19
[1]  6  9 12 15 18 21 24 27
[1] 10 14 18 22 26 30 34
[1] 15 20 25 30 35 40
[1] 21 27 33 39 45
[1] 28 35 42 49
[1] 36 44 52
[1] 45 54
[1] 55

这可能比“RcppRoll”解决方案更为基本。 我还使用大小为10 ^ 6的矢量检查了速度:

> vec <- sample(1000000) / 1000000
> k <- 1000
> system.time(for (i in (1:100)){ k*rollmean(vec,k)})/100
       User      System verstrichen 
     1.2972      0.0000      1.3075