class
属性(S3)に新しいラベルを追加するか、新しい親クラス(S4)を定義することによって、基本的なlengths()
の操作が大幅に遅くなることに気がつきました。リストをクラス分けすると、lengths()関数が遅くなるのはなぜですか?
これは、lengths()
を呼び出す前に、常に「クラスリスト」のクラスを解除する必要があることを示しています。これがなぜ起こるか
は誰
は説明でき、および/または
は、よりよい解決策を提案する(または差異が絶対的にちょうどマイクロ秒であるので、これは本当に重要 ない理由を説明します) 。
再現コード:
# create a list of 1,000 elements with variable letter lengths
mylist <- list()
length(mylist) <- 1000
set.seed(99)
mylist <- lapply(mylist, function(x) sample(LETTERS, size = sample(1:100, size = 1),
replace = TRUE))
# create an S3 "classed" version
mylist_S3classed <- mylist
class(mylist_S3classed) <- c("myclass", "list")
# create an S4 classed version
setClass("mylist_S4class", contains = "list")
mylist_S4classed <- new("mylist_S4class", mylist)
# compare timings of lengths
microbenchmark::microbenchmark(lengths(mylist),
lengths(mylist_S3classed),
lengths(mylist_S4classed),
unit = "relative")
## Unit: relative
## expr min lq mean median uq max neval
## lengths(mylist) 1.0000 1.0000 1.0000 1.00000 1.00000 1.00000 100
## lengths(mylist_S3classed) 125.1433 119.3588 103.9747 91.90734 89.56034 291.97767 100
## lengths(mylist_S4classed) 162.4045 155.4870 119.0611 120.20908 111.95417 67.55309 100
## in absolute timings
microbenchmark::microbenchmark(lengths(mylist),
lengths(mylist_S3classed),
lengths(mylist_S4classed))
## Unit: microseconds
## expr min lq mean median uq max neval
## lengths(mylist) 6.401 6.9475 9.66612 9.4620 10.577 29.237 100
## lengths(mylist_S3classed) 792.738 851.0895 911.97067 898.0955 939.558 1604.189 100
## lengths(mylist_S4classed) 1050.448 1104.7920 1293.63965 1173.4545 1229.485 6431.130 100
短い答え:メソッドをディスパッチすると処理が遅くなります。 –
興味深いことに、実際の方法を定義することで、Rは連続した環境で絶望的にそれを見つけ出すことなく1つを探すのに役立ちます。例えば。 'mylist_S3classed =構造体(mylist、クラス= c(" myclass "、" list ")); mylist_S3classed2 =構造体(mylist、クラス= c( "myclass2"、 "list")); lengths.myclass2 = function(x、use.names = TRUE)NextMethod();マイクロベンチマーク::マイクロベンチマーク(長さ(mylist)、長さ(mylist_S3classed)、長さ(mylist_S3classed2)) ' –
これは完璧な@alexis_lazで、バリアントは私の問題をちょうど解決しました。ありがとう! –