列表元素提取哪个更快,[[或$?

时间:2014-07-29 08:29:26

标签: r performance list subset

所以,我注意到this question提到了一个人使用[[比列表元素提取速度快$的经验,但是我想知道是否有人确定回答R版本> = 3.0.2?

我的一位同事已经看到情况$更快,但这是前一段时间(和Rcpp一起),我想知道R的进化是否有任何改变。

2 个答案:

答案 0 :(得分:5)

为您的案例运行一些基准测试。像这样:

mylist <- replicate(1e2, list(rnorm(1e3), sample(LETTERS, 1e2, TRUE)))
names(mylist) <- paste("X", seq_along(mylist))

library(rbenchmark)
benchmark(for (i in seq_len(1e4)) mylist$X1,
          for (i in seq_len(1e4)) mylist$"X1",
          for (i in seq_len(1e4)) mylist[["X1"]],
          for (i in seq_len(1e4)) mylist[["X1", exact = FALSE]],
          for (i in seq_len(1e4)) mylist[[1]],
          for (i in seq_len(1e4)) mylist$X50,
          for (i in seq_len(1e4)) mylist$"X50",
          for (i in seq_len(1e4)) mylist[["X50"]],
          for (i in seq_len(1e4)) mylist[["X50", exact = FALSE]],
          for (i in seq_len(1e4)) mylist[[50]],
          for (i in seq_len(1e4)) mylist$X100,
          for (i in seq_len(1e4)) mylist$"X100",
          for (i in seq_len(1e4)) mylist[["X100"]],
          for (i in seq_len(1e4)) mylist[["X100", exact = FALSE]],
          for (i in seq_len(1e4)) mylist[[100]],
          replications=100,
          columns=c('test', 'elapsed', 'replications', 'relative'),
          order='relative')

#                                                        test elapsed replications relative
#5                      for (i in seq_len(10000)) mylist[[1]]    0.20          100     1.00
#10                    for (i in seq_len(10000)) mylist[[50]]    0.22          100     1.10
#15                   for (i in seq_len(10000)) mylist[[100]]    0.22          100     1.10
#8                  for (i in seq_len(10000)) mylist[["X50"]]    2.76          100    13.80
#3                   for (i in seq_len(10000)) mylist[["X1"]]    2.87          100    14.35
#13                for (i in seq_len(10000)) mylist[["X100"]]    2.87          100    14.35
#6                       for (i in seq_len(10000)) mylist$X50    4.48          100    22.40
#7                       for (i in seq_len(10000)) mylist$X50    4.49          100    22.45
#12                     for (i in seq_len(10000)) mylist$X100    4.63          100    23.15
#1                        for (i in seq_len(10000)) mylist$X1    4.64          100    23.20
#2                        for (i in seq_len(10000)) mylist$X1    4.66          100    23.30
#11                     for (i in seq_len(10000)) mylist$X100    4.67          100    23.35
#9   for (i in seq_len(10000)) mylist[["X50", exact = FALSE]]    5.56          100    27.80
#4    for (i in seq_len(10000)) mylist[["X1", exact = FALSE]]    5.62          100    28.10
#14 for (i in seq_len(10000)) mylist[["X100", exact = FALSE]]    5.76          100    28.80

R.version
#platform       x86_64-w64-mingw32          
#arch           x86_64                      
#os             mingw32                     
#system         x86_64, mingw32             
#status                                     
#major          3                           
#minor          1.1                         
#year           2014                        
#month          07                          
#day            10                          
#svn rev        66115                       
#language       R                           
#version.string R version 3.1.1 (2014-07-10)
#nickname       Sock it to Me 

答案 1 :(得分:4)

我认为链接的Q&amp; A应该真的回答这个问题,但我认为答案是,取决于。我认为重要的是[[ 设计尽可能快,给定默认值exact=TRUE,因此除非您有特定原因,否则应该是goto方法做其他事情(其他人可能不同意)。以下是源代码的注释。以下内容来自/src/main/subset.c。行号用于参考:

[子集:

  #635 /* The "[" subset operator.
  #636  * This provides the most general form of subsetting. */
  #637 
  #638 SEXP attribute_hidden do_subset(SEXP call, SEXP op, SEXP args, SEXP rho)
  #639 { ... }

[[子集:

  #865 /* The [[ subset operator.  It needs to be fast. */
  #866 /* The arguments to this call are evaluated on entry. */
  #867 
  #868 SEXP attribute_hidden do_subset2(SEXP call, SEXP op, SEXP args, SEXP rho)
  #869 { ... }

$子集:

 #1105 /* The $ subset operator.
 #1106    We need to be sure to only evaluate the first argument.
 #1107    The second will be a symbol that needs to be matched, not evaluated.
 #1108 */
 #1109 SEXP attribute_hidden do_subset3(SEXP call, SEXP op, SEXP args, SEXP env)
 #1110 { ... }