Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

Rのループ内でベクトルの要素を一つ一つ処理した場合の遅さを体感する

More than 5 years have passed since last update.

ループ演算とベクトル演算

一般的なプログラミング言語では、次のような構文がよく使用されます。
※例:a_1 = 1, a_2 = 2, ... という数列をつくり、a_1+a_2,a_2+a_3,...という数列を計算する

コード断片(C#)
//初期化
int[] a = new a[20000];
for(int i = 0;i < 20000; i++){
    a[i] = i;
}
//計算
int[] b = new b[20000];
for(int i = 0;i < 19999; i++){
    b[i] = a[i] + a[i + 1];
}

これを、「愚直に」Rでやった場合には、次のようなソースになります。

loop.r
#初期化
df <- data.frame(a=1:20000)
#計算(aには1でアクセスできる)
for(i in 1:19999){
  df[i,2] <- df[i,1] + df[i+1,1]
}

これは結構時間がかかります。
Rでは、配列についてforなどのループを明示的に記入するよりも、ベクトル演算を駆使した方が処理が速くなります。

vector.r
#初期化
df <- data.frame(a=1:20000)
#計算
df$b <- df$a + c(df$a[2:20000],1)

ポイントは、
・ベクトル演算は同じ長さでないと行えない
・df\$aは(1列)20000行のベクトル
・df\$a[2:20000]はdf\$aの2行目の要素から20000行目の要素までのベクトル
・df\$a[2:20000]の後ろに要素を一つ追加するためにcを利用する
といったところです。

性能比較

性能の比較をするために、次のようなコードを実行してみます。

test.r
df <- data.frame(a=1:20000)
print("for loop test")
date()
for(i in 1:19999){
  df[i,2] <- df[i,1]+df[i+1,1]
}
date()
print("vector test")
df$b <- df$a + c(df$a[2:20000],1)
date()
print("test was over")
実行結果
[1] "for loop test"
[1] "Sat Oct 17 17:11:43 2015"
[1] "Sat Oct 17 17:11:45 2015"
[1] "vector test"
[1] "Sat Oct 17 17:11:45 2015"
[1] "test was over"

forでループする処理では2秒程度の処理時間がかかっていますが、vectorの場合は1秒未満であることがわかります。(core i5 4300U)
いまは20000個でテストしていますが、100000個になると、forのものは数分応答無し、vectorのものは相変わらず一瞬で応答があります。

ということで、ベクトル演算を有効活用しましょう。

sasanquaneuf
座敷わらしになれる日を夢見て日々過ごしている一児の父です。 画像は「R」的なアレにインスパイアされて手書きで書いた「いぬ」です。 中学生の頃はVBなど。大学生の頃はC++ / Haskell / mathematica など。SIer時代はQlik Sense / R / C# / Java / PHP / JavaScript など。 最近は Python / TypeScript など。
https://qiitadon.com/@sasanquaneuf
uniaim
心と歴史を動かす。Tabレジ、Event Manager+、Point Manager、PREORDER、CASHIER等のサービス提供と、端末レンタル・イベント運営などを行っています。
https://uniaim.co.jp
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away