(編集:ここでの問題の1つはスケールです。つまり、1行で機能するものは、200,000 * 50データフレームでRを爆破/クラッシュさせます。たとえば、ハングを避けるために、行単位ではなく列単位でstrptimeを適用する必要があります.私はあなたが実際に 200,000 * 50 で実行した実用的なコード ソリューションを探しています 200,000 * 50 測定されたランタイムを含む ,カジュアルな「これは簡単です」という発言だけではありません.間違った fn を選択すると、12 時間以上のランタイムを簡単に取得できます.次に、私も私のゼロ時間調整コードをより速くするように頼まれました. それが完了するまで仕事は終わりません. 今まで誰もそれを試みませんでした.)
次のマルチステップの対数時間変換をミリ秒の精度でベクトル化し、加速しstrtime()
log()
たいと考えています。単一の数値への変換、続いて減算、そして大きなデータ フレーム(200,000 行 * 300 列、その他の (時間以外の) 列)への変換が含まれます。省略)。以下のコード。それをベクトル化して高速にするだけでなく、追加の問題は、各ステップで (より高次元の) 中間値をどのように表現するのが最適なのかわかりません (たとえば、strtime、行列、ベクトルからのリスト)。私はすでに試しapply,sapply,lapply,vapply,ddply::maply(),...
ましたが、中間フォーマットの非互換性が私を混乱させ続けています...
各行にはtime1..time50 (chr, format="HH:MM:SS.sss") の 50 列があり、時間をミリ秒単位の文字列として表します。ミリ秒の精度が必要です。各行内で、列time1..time50は減少しない順序であり、それらをtime50より前の時間のログに変換したいと考えています。変換 fnparse_hhmmsecms()
は一番下にあり、深刻なベクトル化と高速化が必要です。代替バージョンがコメントアウトされていることがわかります。私がこれまでに考えたこと:(strtime()
複数の)substr()
呼び出しよりも高速です。次に、何らかの方法で3つの数値のリストに(hh,mm,sec.ms)
変換し、次のステップでベクトル乗算する必要があると仮定してベクトルに変換します%*% c(3600,60,1)
数値秒に変換します。これは、各行と各時間文字列に対して私が行うことの擬似コードです。完全なコードは一番下にあります:
for each row in dataframe { # vectorize this, loop_apply(), or whatever...
#for each time-column index i ('time1'..'time50') { # vectorize this...
hhmmsecms_50 <- parse_hhmmsecms(xx$time50[i])
# Main computation
xx[i,Clogtime] <- -10*log10(1000*(hhmmsecms_50 - parse_hhmmsecms(xx[i,Ctime]) ))
# Minor task: fix up all the 'zero-time' events to be evenly spaced between -3..0
#}
}
したがって、関連する 5 つのサブ問題があります。
- によって返されたリストの処理をベクトル化する方法は
strtime()
? 3 つの項目のリストを返すため、2D データフレームまたは時間文字列の 1D 行を渡すと、3D または 2D の中間オブジェクトが取得されます。(内部的に list-of-list を使用しますか? リストのマトリックス? リストの配列?) - 関数全体をベクトル化する方法は
parse_hhmmsecms()
? - 次に、減算を行い、ログに記録します
- ゼロタイム修正コードもベクトル化します (これは現在、最も遅い部分です)。
- ステップ 1 ~ 4 を加速する方法は?
10 個のサンプル列を使用した以下のコード スニペットtime41..50
(random_hhmmsecms()
より大きなサンプルが必要な場合に使用)
私はこれらの推奨事項に従うために最善を尽くしました。これは、6時間の作業で得られる再現性です。
# Each of 200,000 rows has 50 time strings (chr) like this...
xx <- structure(list(time41 = c("08:00:41.465", "08:00:50.573", "08:00:50.684"
), time42 = c("08:00:41.465", "08:00:50.573", "08:00:50.759"),
time43 = c("08:00:41.465", "08:00:50.573", "08:00:50.759"
), time44 = c("08:00:41.465", "08:00:50.664", "08:00:50.759"
), time45 = c("08:00:41.465", "08:00:50.684", "08:00:50.759"
), time46 = c("08:00:42.496", "08:00:50.684", "08:00:50.759"
), time47 = c("08:00:42.564", "08:00:50.759", "08:00:51.373"
), time48 = c("08:00:48.370", "08:00:50.759", "08:00:51.373"
), time49 = c("08:00:50.573", "08:00:50.759", "08:00:54.452"
), time50 = c("08:00:50.573", "08:00:50.759", "08:00:54.452"
)), .Names = c("time41", "time42", "time43", "time44", "time45",
"time46", "time47", "time48", "time49", "time50"), row.names = 3:5, class = "data.frame")
# Handle millisecond timing and time conversion
options('digits.secs'=3)
# Parse "HH:MM:SS.sss" timestring into (numeric) number of seconds (Very slow)
parse_hhmmsecms <- function(t) {
as.numeric(substr(t,1,2))*3600 + as.numeric(substr(t,4,5))*60 + as.numeric(substr(t,7,12)) # WORKS, V SLOW
#c(3600,60,1) %*% sapply((strsplit(t[1,]$time1, ':')), as.numeric) # SLOW, NOT VECTOR
#as.vector(as.numeric(unlist(strsplit(t,':',fixed=TRUE)))) %*% c(3600,60,1) # WANT TO VECTORIZE THIS
}
random_hhmmsecms <- function(n=1, min=8*3600, max=16*3600) {
# Generate n random hhmmsecms objects between min and max (8am:4pm)
xx <- runif(n,min,max)
ss <- xx %% 60
mm <- (xx %/% 60) %% 60
hh <- xx %/% 3600
sprintf("%02d:%02d:%05.3f", hh,mm,ss)
}
xx$logtime45 <- xx$logtime44 <- xx$logtime43 <- xx$logtime42 <- xx$logtime41 <- NA
xx$logtime50 <- xx$logtime49 <- xx$logtime48 <- xx$logtime47 <- xx$logtime46 <- NA
# (we pass index vectors as the dataframe column ordering may change)
Ctime <- which(colnames(xx)=='time41') : which(colnames(xx)=='time50')
Clogtime <- which(colnames(xx)=='logtime41') : which(colnames(xx)=='logtime50')
for (i in 40:nrow(xx)) {
#if (i%%100==0) { print(paste('... row',i)) }
hhmmsecms_50 <- parse_hhmmsecms(xx$time50[i])
xx[i,Clogtime] <- -10*log10(1000*(hhmmsecms_50 - parse_hhmmsecms(xx[i,Ctime]) ))
# Now fix up all the 'zero-time' events to be evenly spaced between -3..0
Czerotime.p <- which(xx[i,Clogtime]==Inf | xx[i,Clogtime]>-1e-9)
xx[i,Czerotime.p] <- seq(-3,0,length.out=length(Czerotime.p))
}