1

大規模なデータセット(〜10,000個の曲線にグループ化された〜10,000個のデータポイント)に対して探索的分析を行っています。RStudioのパッケージを使用してmanipulate、x 軸の制限を変更しています。問題は、プロットが新しいパラメーターで再描画されるのに 5 秒以上かかることです。これを少しだけスピードアップする方法を望んでいます。latticeパッケージを使用しています。これは簡単な例です...

set.seed(100)
x = rep(1:5,20)
y = rnorm(100)
groups = gl(20,5)
p = xyplot(y~x,groups=groups,type="l",
           auto.key=list(space="right",lines=TRUE,
                         points=TRUE,rectangles=TRUE) )

Rprof(interval=0.001)
print(p)
Rprof(NULL)
head( summaryRprof()$by.total )
                  total.time total.pct self.time self.pct
"print"                0.239    100.00     0.000     0.00
"printFunction"        0.239    100.00     0.000     0.00
"print.trellis"        0.239    100.00     0.000     0.00
"do.call"              0.126     52.72     0.001     0.42
"draw.key"             0.098     41.00     0.001     0.42
"evaluate.legend"      0.098     41.00     0.000     0.00

draw.key実行時間の 41% を占めることに注意してください(そうです、この余分な凡例は、私の主張を強調するために選択されました)。私の目的のために、私の伝説は決して変わりませんが、プロットは変わります. 1 つのプロットから凡例、キー、または何かを保存して、何度も再利用する方法はありますか (おそらくGrobからオブジェクトを再利用しますlattice::draw.key)。のコードの一部を調べlattice:::plot.trellisたところ、これを行う方法があるはずです。ただし、そのためにはかなりの量の新しいコードが必要になるようです。簡単な解決策はありますか?または、速度で知られている他のプロット関数またはパッケージはありますか? もちろん、滑らかな曲線をデータに合わせて「圧縮/ダウンサンプリング」することはできますが、これはしたくありません。

4

2 に答える 2

1

要するに、はい、事前に計算されたグリッド オブジェクトまたはその他のパラメーターに基づいて格子プロットの印刷を高速化する方法があります。しかし、私の知る限り、簡単な解決策はありません。そのためには、格子プロット関数のソースを掘り下げて、plot.trellis速度を最適化できる場所を特定する必要がありました。質問の例から続けて...

# Save the legend from the last plot
plot.grob = trellis.last.object()
legend.grob = lattice:::evaluate.legend( plot.grob$legend )

# Modify the default plotting function
f = lattice:::plot.trellis
b = body(f)
fun.line = which(!is.na(str_match(as.character(b),"evaluate.legend")))
new.line = substitute(legend <- if(is.null(legend.object)) 
                        evaluate.legend(x$legend) else legend.object)
body(f)[[fun.line]] = new.line
args = formals(f)
formals(f) = do.call(alist, c( args[2:length(args)-1], alist(legend.object=NULL,...=)) )

# Note that evaluate.legend is no longer taking up any time because it's not called
Rprof()
f(plot.grob,legend.object=legend.grob)
Rprof(NULL)
head(summaryRprof()$by.total)

# the modified function is faster
times = data.frame( modified.fun=NA, standard.fun=NA )
for( i in 1:100 ) {
  t1 = profr( f(plot.grob,legend.object=legend.grob), interval=0.001 )[1,"time"]
  t2 = profr( plot(plot.grob), interval=0.001 )[1,"time"]
  times = rbind( times, c( t1, t2 ) )
}
colMeans(na.omit(times))
modified.fun standard.fun 
     0.11435      0.19757

変更された関数の所要時間は約 40% 短縮されます。これは、質問に示されている例evaluate.legendでは実行時間の約 40% が呼び出しにかかるため、理にかなっています。関数には、速度を最適化できるplot.trellis他の多くのスポットもありました。このまま進めば、パッケージplot.trellisの関数のみが呼び出されるように、最終的には関数を必要最小限に抑えることができます。これは本質的に、柔軟性は低下しますが速度は向上するgrid、まったく新しい関数を書き直すことになります。plot.trellisしかし、これは私が望んでいたものではありません。

余談ですが、画面上にプロットを実際に描画するのに、プロファイリング コードで報告された実行時間よりも時間がかかることに気付きました。ストップウォッチを使用して、コードの実行が完了したと報告された後、プロットが表示されるまでに 1 秒弱かかる時間を計りました。依存している他のプロットパッケージを試してみたgridところ、同様の結果が見つかりました。したがって、プロット関数がどれだけ最適化されていてもgrid、時間が 1 秒以下になると、最終的に 、ベース R、またはハードウェアのいずれかが制限要因になると判断しました。この新しい問題には解決策がありますが、それは別のトピックです...

于 2013-11-04T03:45:36.193 に答える
1

画面にプロットしてからファイルを開くよりも、ファイルにプロットする方が速いことが時々あります。

それはあなたが探しているものではありませんが、十分に高速であれば、はるかに簡単になります...

于 2013-10-30T01:49:11.490 に答える