r语言 - 用于寻址数据框元素的索引序列



几种方法可以访问数据框中的特定元素,使用括号([ ](和美元符号($(的各种组合。在时间敏感的函数中,使用哪一个可能很重要?

对一些可能的组合进行基准测试:

library(microbenchmark)
df <- data.frame(a=1:6,b=1:6,c=1:6,d=1:6,e=1:6,f=1:6)
microbenchmark(df$c[3],
               df[3,]$c,
               df[3,3],
               df[3,][3],
               df[3,][[3]],
               df[,3][3],
               times=1e3)

产生以下计时:

Unit: microseconds
         expr    min       lq      mean   median       uq      max neval
      df$c[3]  9.836  11.4505  14.03068  12.2015  12.9280 1252.854  1000
    df[3, ]$c 77.204  89.5750 100.18752  92.2445  98.6395 1351.521  1000
     df[3, 3] 15.719  18.9850  21.04074  19.6010  20.7400   82.519  1000
   df[3, ][3] 88.599 100.5920 110.59009 104.0415 110.5435  409.050  1000
 df[3, ][[3]] 75.856  87.2200  98.67104  89.9360  96.1695 1391.299  1000
   df[, 3][3] 11.639  13.4225  14.77493  13.9510  14.6905   55.172  1000

我们看到df$c[3]最快的地方,紧随其后的是df[,3][3] .其他人要慢得多。

在时间敏感的应用程序中,我经常使用数据表而不是帧,因为排序子集操作通常要快得多。但是,寻址操作可能会慢得多,正如我们看到的,如果我们对data.table重复上述操作:

library(data.table)
dt <- as.data.table(df)
microbenchmark(dt$c[3],
               dt[3,]$c,
               dt[3,3],
               dt[3,][[3]],
               times=1e3)
Unit: microseconds
         expr     min       lq      mean   median       uq      max neval
      dt$c[3]   9.503  11.4020  14.90066  12.6820  13.8950 1336.407  1000
    dt[3, ]$c 417.756 437.0495 480.26532 448.8625 463.6350 2909.038  1000
     dt[3, 3] 205.115 218.9590 238.78000 227.9575 239.1265 1554.503  1000
 dt[3, ][[3]] 414.378 435.2115 470.76853 447.1505 461.3310 1906.432  1000

我的问题是:$[ ]是否保证始终是最快的寻址方法,或者这是否取决于数据框(或表(、平台 (OS( 或构建版本中的数据类型等因素? 如果有人能解释时间差异背后的原因,和/或各种方法的优缺点,那也是有用的。

更新

按照 42

的答案中的建议,在这里使用更多的行和来自 42 的额外语法选项以及 A.Webb 的评论中的其他语法选项重复测试,他建议 df[[3,3]] 作为最快的。(注意:我也尝试了相同的测试,但访问了更高的行号,但时间似乎与选择哪一行无关(。

df <- data.frame(a=1:1000,b=1:1000,c=1:1000,d=1:1000,e=1:1000,f=1:1000)
Unit: microseconds
         expr    min      lq       mean  median       uq      max neval
      df$c[3]  8.314  9.7610  12.870667 10.6260  12.0950 1250.339  1000
 df[["c"]][3]  6.932  8.0670   9.652672  8.7075   9.9445   26.512  1000
  (df[3, ])$c 72.395 77.2390  90.893724 79.8320  95.8540  256.082  1000
     df[3, 3] 14.871 16.2625  19.377482 17.1180  20.1720   47.720  1000
   df[3, ][3] 82.446 86.7680 102.462603 89.9660 107.7965  232.685  1000
 df[3, ][[3]] 70.559 75.2140  93.581394 78.3385  93.4235 1507.933  1000
   df[, 3][3]  9.933 11.4770  13.430309 12.1090  14.0900   38.213  1000
   df[[3, 3]]  6.465  7.8355   9.236773  8.4500   9.6355   29.833  1000

所以看起来 df[[i,j]] 是最快的,紧随其后的是 df[["colname"]][j]。使用其中哪一个可能取决于您是否需要使用列名或数字。

如果我们可以假设所有平台和所有数据类型始终如此,那么问题仍然悬而未决。

正如我的评论中所述,df$c[3]实际上被解析为 '[['(df, 'c')[3] ,因此跳过解析过程会导致更快的执行也就不足为奇了。data.table 比较大多是非等效的,除非使用 $ 它不是真正的 data.table 函数。

Unit: microseconds
         expr     min       lq      mean   median       uq      max neval   cld
      df$c[3]  16.035  16.8245  17.63600  17.3090  17.9400   31.158  1000 ab   
 df[["c"]][3]  13.008  13.9090  14.60883  14.2775  14.8355  121.634  1000 a    
  (df[3, ])$c 137.376 140.4895 143.57778 141.6055 143.8310  175.180  1000    d 
     df[3, 3]  29.316  30.5715  31.25617  30.9040  31.3165   49.764  1000   c  
   df[3, ][3] 156.524 159.4180 167.99243 160.3910 162.3120 2636.693  1000     e
 df[3, ][[3]] 134.975 137.3945 142.92265 138.3810 140.2370 2675.090  1000    d 
   df[, 3][3]  20.108  21.2860  21.94357  21.5810  21.8640   59.057  1000  b   

承认对我编写的代码感到惊讶:'[['(df, 'c')[3],未解析为df[["c"]][3],并且对某些结果感到困惑,但一般规则是先选择列,然后在结果向量中的位置通常要快得多。

另外:这需要使用较大的对象进行测试。 有行>>列的那些

相关内容

  • 没有找到相关文章

最新更新