このRコードをより効率的にするのを手伝ってくれる人はいますか?
文字列のリストを文字列のベクトルに変更する関数、または数値のリストを数値のベクトルに変更する関数、型指定された要素のリストを特定の型のベクトルに変更する関数を作成しようとしています。
リストに次のプロパティがある場合、リストを特定のタイプのベクトルに変更できるようにしたい:
それらは均一に型付けされます。リストのすべての要素は、「文字」または「複合」などのタイプです。
リストの各要素の長さは 1 です。
as_atomic <- local({ assert_is_valid_elem <- function (elem, mode) { if (length(elem) != 1 || !is(elem, mode)) { stop("") } TRUE } function (coll, mode) { if (length(coll) == 0) { vector(mode) } else { # check that the generic vector is composed only # of length-one values, and each value has the correct type. # uses more memory that 'for', but is presumably faster. vapply(coll, assert_is_valid_elem, logical(1), mode = mode) as.vector(coll, mode = mode) } } })
例えば、
as_atomic(list(1, 2, 3), 'numeric')
as.numeric(c(1,2,3))
# this fails (mixed types)
as_atomic( list(1, 'a', 2), 'character' )
# ERROR.
# this fails (non-length one element)
as_atomic( list(1, c(2,3,4), 5), 'numeric' )
# ERROR.
# this fails (cannot convert numbers to strings)
as_atomic( list(1, 2, 3), 'character' )
# ERROR.
上記のコードは正常に動作しますが、非常に遅く、関数の動作を変更せずに最適化する方法がわかりません。関数「as_atomic」がそのように動作することが重要です。よく知っている基本機能 (たとえば、リスト解除) に切り替えることができません。これは、不適切なリストに対してエラーをスローする必要があるためです。
require(microbenchmark)
microbenchmark(
as_atomic( as.list(1:1000), 'numeric'),
vapply(1:1000, identity, integer(1)),
unit = 'ns'
)
私の (かなり高速な) マシンでは、ベンチマークの周波数は約 40 Hz であるため、この関数はほとんどの場合、私のコードではレート制限になっています。vapply コントロール ベンチマークの周波数は約 1650Hz ですが、それでもかなり遅いです。
この操作の効率を劇的に改善する方法はありますか? アドバイスをいただければ幸いです。
説明や編集が必要な場合は、下にコメントを残してください。
編集:
皆さんこんにちは、
お返事が大変遅くなり申し訳ありません;;これを再実装する前に、必要な試験がありました。
パフォーマンスのヒントをありがとうございました。単純な R コードを使用して、ひどい 40hz から許容範囲内の 600hz にパフォーマンスを上げました。
is; の代わりに typeof または mode を使用することで、最大のスピードアップが実現しました。これにより、タイトな内部チェック ループが実際に高速化されました。
ただし、実際にパフォーマンスを向上させるには、おそらく弾丸をかじってrcppでこれを書き直す必要があります。