Rで,長さ100の数列があって,連続する5個の数の和を全て(96個)欲しいとき,どうすれば賢いかな
リアル・マネーボール界隈では超有名で、知らない人はもぐりと言われるブログである
の著者@gg_hatano氏が
Rで, 長さ100の数列があって, 連続する5個の数の和を全て(96個)欲しいとき,
どうすれば賢いかな
— はたむ (@gg_hatano) 2014, 4月 28
なことを呟いていたので、@gg_hatano library(xts) rollapplyr(1:10, 3, sum)なコードで、[1] 6 9 12 15 18 21 24 27となります。あとは…わかるな?
— パイレーツ・オブ・テラモナギ (@teramonagi) 2014, 4月 28
って回答したんだけど、桃尻おじさんが@gg_hatano @teramonagi library(RcppRoll);roll_sum(1:10,n=3)もええで
— 尻白 (@dichika) 2014, 4月 29
なんてこと仰ってて、更に@kohske氏が@gg_hatano 100要素程度ならrowSums(embed(x, 5))が簡単かもしれませんね。embedは結構使える状況があります。
— kohske (@kohske) 2014, 4月 28
なんて仰るもんですから、速度比較してみたら
> system.time(rollapplyr(1:10^6, 3, sum)) ユーザ システム 経過 20.76 0.00 21.33 > system.time(roll_sum(1:10^6, 3)) ユーザ システム 経過 0 0 0 > system.time(rowSums(embed(1:10^6, 3))) ユーザ システム 経過 0.07 0.01 0.08
となりました。うん、あとはもう…わかるな?
ついでにF#版。rollapplyrよりは段違いで速いけど、embed版よりも遅い。
もうちょっと数増やした方がよさげか…と思って、増やしてみたらR側もF#側もOut of Memoryエラー食らったので諦め。
> #time "on";; --> Timing now on > let x = [1..1000000] |> Seq.windowed 3 |> Seq.map Array.sum |> Seq.toArray;; Real: 00:00:00.438, CPU: 00:00:00.561, GC gen0: 19, gen1: 5, gen2: 1 val x : int [] = [|6; 9; 12; 15; 18; 21; 24; 27; 30; 33; 36; 39; 42; 45; 48; 51; 54; 57; 60; 63; 66; 69; 72; 75; 78; 81; 84; 87; 90; 93; 96; 99; 102; 105; 108; 111; 114; 117; 120; 123; 126; 129; 132; 135; 138; 141; 144; 147; 150; 153; 156; 159; 162; 165; 168; 171; 174; 177; 180; 183; 186; 189; 192; 195; 198; 201; 204; 207; 210; 213; 216; 219; 222; 225; 228; 231; 234; 237; 240; 243; 246; 249; 252; 255; 258; 261; 264; 267; 270; 273; 276; 279; 282; 285; 288; 291; 294; 297; 300; 303; ...|]
お手元の環境でお試しの際には
install.packages(c("xts", "RcppRoll")) library(xts) library(RcppRoll)
を忘れずに。
ここでは連続する数値の和で計算したが、その他のそれっぽい関数系まとめは
を読め。