我刚刚注意到,通过向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
答案 0 :(得分:5)
这个额外时间是R找到正确的length
函数的时间。对于一个普通的旧列表,它非常容易和优化,它可能存储在对象中。得到它,归还它。
对于一个被分类的对象,无论是S3还是S4,R必须找到正确的length
函数,因为length
可以被定义为一种方法。所以R必须继续进行搜索,在你的情况下它会随处可见,直到它达到默认值。当它完成时,它花了那些毫秒。
除非你能告诉你未来的自己,你永远不会在这些对象上写length
方法,因为你的代码会破坏...