我刚刚注意到,通过向class属性添加附加标签(S3)或定义新的父类(S4)来对列表进行分类会大大减慢基本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
Run Code Online (Sandbox Code Playgroud)
这个额外时间是R找到正确length功能所需的时间.对于一个普通的旧列表,它非常容易和优化,它可能存储在对象中.得到它,归还它.
对于一个被分类的对象,无论是S3还是S4,R必须找到正确的length函数,因为它length可以被定义为一种方法.所以R必须继续进行搜索,在你的情况下它会随处可见,直到它达到默认值.当它完成时,它花了那些毫秒.
除非你可以告诉你未来的自己,你永远不会length在这些对象上写一个方法,因为你的代码会破坏,所以不要去取消分类以试图加快速度.