【问题标题】:Getting a performance gain out of setkey从 setkey 获得性能提升
【发布时间】:2016-02-16 09:25:05
【问题描述】:

我已阅读文档 vignette("datatable-intro") 和一些关于该主题的在线资源,例如 this

但是我仍然很难看到使用 data.table 的 setkey 的性能提升(尽管我发现它比基本 [dplyr::filter 快得多,即使没有密钥集)。

任何想法为什么?我的例子是否很小/很容易看到性能提升?还是我做错了什么?

我期待使用密钥的 dtk 更快。

library(data.table)
library(microbenchmark)

df = data.frame(l = letters, n = 1:26)
df = do.call(rbind, replicate(1e4, df, FALSE))
dfdt = dfdtk = data.table(df)
setkey(dfdtk, l)

mb = microbenchmark(times = 10, unit = "s",
  base = df[df$l == "a",],
  dt = dfdt[l == "a"],
  dtl = dfdt[list("a")],
  dtk = dfdtk[list("a")]
)
plot(mb)

【问题讨论】:

    标签: r performance data.table subset


    【解决方案1】:

    我找到了 3 个需要修复或改进的地方。

    1. =操作员不会复制data.table,后面setkey会在两个data.tables上设置key,所以copy是必须的。
    2. ad-hoc join 没有键,还不能使用索引,但这是计划的。
    3. dfdt[l == "a"] 将在第一次尝试时建立索引并重复使用它,因此没有索引的基准值得添加。

    library(data.table)
    library(microbenchmark)
    op = options("datatable.auto.index" = TRUE) # default!
    
    df = data.frame(l = letters, n = 1:26)
    df = do.call(rbind, replicate(1e4, df, FALSE))
    dfdtk = as.data.table(df)
    dfdt = copy(dfdtk) # fix #1
    setkeyv(dfdtk, "l")
    stopifnot(
        is.null(key(dfdt)),
        key(dfdtk) == "l"
    )
    
    mb = microbenchmark(times = 10, unit = "s",
                        base = df[df$l == "a",],
                        dt = dfdt[l == "a"],
                        dtl = dfdt[list("a"), on = c("l" = "V1")], # fix #2
                        dtk = dfdtk[list("a")])
    print(mb)
    #Unit: seconds
    # expr         min          lq         mean       median          uq         max neval
    # base 0.016255351 0.017294076 0.0177331871 0.0178513590 0.018269365 0.019392296    10
    #   dt 0.000792324 0.000819030 0.0011565028 0.0009645955 0.001056976 0.002278742    10
    #  dtl 0.001625836 0.001657269 0.0018865184 0.0019408475 0.002009650 0.002196615    10
    #  dtk 0.000566798 0.000598538 0.0007664731 0.0007530190 0.000897327 0.001008621    10
    
    options("datatable.auto.index" = FALSE) # fix #3
    stopifnot(
        key2(dfdt) == "l",
        is.null(key2(set2keyv(dfdt, NULL)))
    )
    mb = microbenchmark(times = 10, unit = "s",
                        base = df[df$l == "a",],
                        dt = dfdt[l == "a"],
                        dtl = dfdt[list("a"), on = c("l" = "V1")],
                        dtk = dfdtk[list("a")])
    print(mb)
    #Unit: seconds
    # expr         min          lq         mean       median          uq         max neval
    # base 0.015935139 0.017397039 0.0253407267 0.0180737620 0.019560766 0.090317493    10
    #   dt 0.014194243 0.014292279 0.0153187365 0.0153102030 0.015997166 0.016689574    10
    #  dtl 0.001628532 0.001774283 0.0020169391 0.0018818880 0.001935386 0.003697506    10
    #  dtk 0.000556702 0.000653134 0.0006869461 0.0006898765 0.000764199 0.000780357    10
    
    options(op)
    

    抱歉stopifnots,需要进行大量单元测试...

    【讨论】:

      猜你喜欢
      • 2011-07-17
      • 2012-01-15
      • 1970-01-01
      • 2014-09-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-05
      • 1970-01-01
      相关资源
      最近更新 更多