【问题标题】:What algorithm does R use to search through data frames?R 使用什么算法搜索数据帧?
【发布时间】:2020-04-14 05:39:02
【问题描述】:

原生 R 中的 which() 方法使用什么算法来搜索数据帧?例如,如果我调用

df[which(df$parameter == 3)]

R 使用什么算法来搜索这个数据框?二进制搜索?线性搜索?我在任何地方都找不到这方面的文档。如果它不使用上述任何一种,它使用什么算法,它的时间复杂度是多少?

【问题讨论】:

    标签: r algorithm search


    【解决方案1】:

    如果你对这个问题感兴趣,可以关注the datatable vignette on the subject

    默认情况下,R 使用线性搜索。它扫描整个向量。这是data.table 的一大特色,可以让binary search 使用索引表。在data.table 中,索引数据集将在内存中物理排序元素,因此在其中搜索值非常快。 data.table(见here)中的二级索引将启用二分搜索,但数据不会在连续的内存槽中物理重新排序。

    也许data.table 小插图更明确:

    可以看出,每次搜索我们都会将搜索次数减少一半。这就是为什么基于二进制搜索的子集非常快的原因。由于 data.tables 的每一列的行在内存中具有连续的位置,因此操作以非常缓存高效的方式执行(也有助于提高速度)。

    此外,由于我们直接获得匹配的行索引,而无需创建那些巨大的逻辑向量(等于 data.table 中的行数),因此内存效率也很高。

    示例

    让我们看一个例子。包microbenchmark 用于比较。

    我们会比较:

    • (线性)搜索data.frame
    • 使用dplyr 过滤
    • (线性)搜索data.table
    • (二进制)使用主键搜索data.table(使用setkey
    • (二进制)搜索带有辅助键的data.table(使用setindex

    让我们创建所需的每个部分:

    library(data.table)
    library(dplyr)
    
    df <- data.frame(
      x = rnorm(1e6),
      y = rnorm(1e6)
    )
    dt <- as.data.table(df) 
    
    dt2 <- copy(dt)
    dt3 <- copy(dt)
    

    我们将在dt2上设置主键(二分查找+内存中重新排序的对象)和dt3上设置辅助键(二分查找但在内存中没有重新排序)

    setkey(dt2, x)
    setindex(dt3, x)
    

    微基准测试:

    m <- microbenchmark::microbenchmark(
      df[df$x<0,],
      df %>% dplyr::filter(x<0),
      dt[x<0],
      dt2[x<0],
      dt3[x<0],
      times = 20L
    )
    
    m 
    
    Unit: milliseconds
                            expr      min       lq     mean   median       uq       max neval
                  df[df$x < 0, ] 56.56557 57.54392 66.97838 61.39609 75.30391  91.42418    20
     df %>% dplyr::filter(x < 0) 23.24242 24.15183 34.64290 26.02232 34.91405 143.10476    20
                       dt[x < 0] 18.32496 18.96585 21.35255 20.25604 23.02666  33.25656    20
                      dt2[x < 0] 10.85129 10.94804 11.92941 11.21601 11.80469  18.29040    20
                      dt3[x < 0] 18.37789 18.47568 19.51928 18.76135 19.39782  26.90826    20
    

    到目前为止,基本 R 方法是最慢的。在此示例中,使用二级索引并没有提高那么多性能。但是主键可以!

    ggplot2::autoplot(m)
    

    【讨论】:

      猜你喜欢
      • 2023-03-31
      • 1970-01-01
      • 2012-11-01
      • 2012-05-30
      • 1970-01-01
      • 1970-01-01
      • 2019-03-01
      • 2012-04-07
      • 1970-01-01
      相关资源
      最近更新 更多