test <- as.Date("2018-9-13")以下の繰り返し処理で,受験者の試験日での年齢yearを計算できることを確認しました。
for (i in 1:nrow(dat)) {受験者データが大規模ですので,繰り返し処理を高速化したいと思います。
dat$year[i] <- length(seq(dat$birth[i], test, by = "year")) - 1
}
No.22591 Re: 【R】 繰り返し処理の高速化 【青木繁伸】 2018/08/15(Wed) 02:12
50000 人分のテストデータを作ってやってみましたtest <- as.Date("2018-9-13")年齢の計算は,簡単なのです。試験年から生まれ年を引くだけ。
dat <- data.frame(birth=as.Date(Sys.Date()-1:50000)) # 50000 人分のテストデータ
system.time({
for (i in 1:nrow(dat)) {
dat$year[i] <- length(seq(dat$birth[i], test, by = "year")) - 1
}
})
ユーザ システム 経過
11.711 6.689 18.254
ただし,「生まれ月が試験月より後(大きい)なら」,
または,「生まれ月が試験月と同じで,生まれ日が試験日より後(大きい)なら」
1を引く。
わざわざ as.Date となっているけど,そこから年月日(スカラー y, m, d)を取り出す。
試験年月日は yyyy, mm, dd の整数で与える(as.Date から取りだしてもよいけど)age2 <- function(x, yyyy = 2018, mm = 09, dd = 13) {でも,これでは for を含むし,年月日の取り出しコストが掛かるのでかえって遅い。
y <- as.integer(substr(x, 1, 4))
m <- as.integer(substr(x, 6, 7))
d <- as.integer(substr(x, 9, 10))
val <- yyyy - y
if (m > mm || (m == mm && d > dd)) {
val <- val-1
}
val
}
system.time({
for (i in 1:nrow(dat)) {
dat$year2[i] <- age2(dat$birth[i])
}
})ユーザ システム 経過一応答えは合っているようだ。
13.662 6.667 20.312> all(dat$year == dat$year2)for を避けるためにベクトル演算を行うようにする。
[1] TRUE
関数には dat$birth ベクトルを渡す。
年月日の取り出し,それに基づく年齢(val)の計算も全部がベクトル演算。age3 <- function(birth, yyyy = 2018, mm = 09, dd = 13) {27 倍ほど速くなった。
y <- as.integer(substr(birth, 1, 4))
m <- as.integer(substr(birth, 6, 7))
d <- as.integer(substr(birth, 9, 10))
val <- yyyy - y
ifelse(m > mm | (m == mm & d > dd), val-1, val)
}
system.time(dat$year3 <- age3(dat$birth))ユーザ システム 経過答えも合っているようだ。
0.424 0.023 0.448> all(dat$year == dat$year3)なお,val を計算している 2 行を(ifelse を使うのが気持ち悪いからといって)
[1] TRUEyyyy - y - (m > mm | (m == mm & d > dd))にしても,ほとんど速度に違いはない。
年月日が3つのベクトルで与えられれば as.Date から取り出す必要がないのでもっと速い。
birth を "2018-08-15" とわざわざ入力しているのか,2018, 8, 15 という3つの整数を入力しているのかによる。
後者なら,その3つの整数から文字列を作って as.Date していることになる。
3つの整数値を入力してそれをそのまま使うなら,人間もコンピュータも無駄なことをしなくてもよいということになる。
No.22592 御礼(Re: 【R】 繰り返し処理の高速化) 【明石】 2018/08/15(Wed) 08:04
青木先生 様;
お忙しいところを失礼いたします,明石と申します。
多面的にご教示いただき,
特に,for を避けるためにベクトル演算を行うようにするところは,
大変に勉強になります。
毎々,ご丁寧なご教示をいただき,誠にありがとうございます。
心から御礼を申し上げます。
ありがとうございました。
● 「統計学関連なんでもあり」の過去ログ--- 048 の目次へジャンプ
● 「統計学関連なんでもあり」の目次へジャンプ
● 直前のページへ戻る