2016-12-27 2 views
4

class属性(S3)に新しいラベルを追加するか、新しい親クラス(S4)を定義することによって、基本的なlengths()の操作が大幅に遅くなることに気がつきました。リストをクラス分けすると、lengths()関数が遅くなるのはなぜですか?

これは、lengths()を呼び出す前に、常に「クラスリスト」のクラスを解除する必要があることを示しています。これがなぜ起こるか

は誰

  1. は説明でき、および/または

  2. は、よりよい解決策を提案する(または差異が絶対的にちょうどマイクロ秒であるので、これは本当に重要 ない理由を説明します) 。

再現コード:

# 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 
+2

短い答え:メソッドをディスパッチすると処理が遅くなります。 –

+1

興味深いことに、実際の方法を定義することで、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)) ' –

+0

これは完璧な@alexis_lazで、バリアントは私の問題をちょうど解決しました。ありがとう! –

答えて

5

この余分な時間は、Rは右length機能を見つけるのにかかる時間です。普通の古いリストの場合、それはかなり簡単で最適化されているでしょう。おそらくそのオブジェクトの中に格納されています。それを返して、それを返す。

lengthがメソッドとして定義されている可能性があるため、クラス化されたオブジェクトの場合、S3またはS4、Rは右lengthという関数を見つけなければなりません。だから、Rは狩りに行く必要があり、あなたのケースでは、それはデフォルトに落ちるまでどこでも見えます。その時までに、そのミリ秒を過ごした。

試してみて、あなたのコードが解除されますので、あなたは、あなたがこれらのオブジェクトの lengthメソッドを書くことは決してないだろうあなたの未来の自己を伝えることができなければ、これをスピードアップするためにunclassing物事を移動しないでください

...

関連する問題