【问题标题】:Vector subsetting performance: name versus index向量子集性能:名称与索引
【发布时间】:2013-12-17 23:47:25
【问题描述】:

如果我有一个带有名称的向量 v

John       Murray     Lisa       Mike       Joe       Ann 
0.0832090  0.0475580 -0.2797860  0.1086225  0.0104590 -0.0028250 

v['Joe']v[4] 的时间复杂度是多少?我猜前者会采用 O(log n),因为它应该涉及二进制搜索,但我仍然不确定后者是否是 O(1)。

此外,当v 是列表/数据帧而不是原子向量时,结果是否可以推广?

【问题讨论】:

    标签: r


    【解决方案1】:

    在名称查找的情况下,它似乎是大约 O(n),即矢量扫描。您对使用索引进行查找的 O(1) 猜想似乎是合理的......

    #  Unique names for longish vector
    nms <- apply( expand.grid( letters , letters , letters , letters ) , 1 , paste , collapse = "" )
    length(nms)
    #[1] 456976
    length(unique(nms))
    #[1] 456976
    
    #  Start of names
    head(nms)
    #[1] "aaaa" "baaa" "caaa" "daaa" "eaaa" "faaa"
    
    #  End of names
    tail(nms)
    #[1] "uzzz" "vzzz" "wzzz" "xzzz" "yzzz" "zzzz"
    
    #  Large named vector
    x <- setNames( runif( 456976 ) , nms )
    
    #  Small named vector
    y <- setNames( runif(26) , letters )
    
    #  Timing information
    require( microbenchmark )
    bm <- microbenchmark( x['daaa'] , x[4] , x['vzzz'] , x[456972] , y['d'] , y[4] )
    print( bm , order = 'median' , unit = 'relative' , digits = 3 )
    #Unit: relative
    #      expr min       lq   median       uq      max neval
    # x[456972] NaN 1.00e+00     1.00     1.00    1.000   100
    #      x[4] Inf 1.00e+00     1.33     1.07    0.957   100
    #      y[4] NaN 5.01e-01     1.33     1.14    0.191   100
    #    y["d"] Inf 1.00e+00     2.00     1.25    0.265   100
    # x["vzzz"] Inf 6.57e+04 44412.24  9969.64 3439.154   100
    # x["daaa"] Inf 6.59e+04 44582.73 10049.63 1207.337   100
    

    【讨论】:

    • 太棒了!感谢您的回答。另外,您还帮助我学习了一种尝试此类问题的方法。这在将来真的很有用!
    • 比这要复杂一些。有关详细信息,请参阅stackoverflow.com/questions/3470447。另请注意,对 n 次进行子集化比对具有 n 个值的单个子集进行处理要慢得多。
    • @hadley 此代码只为每个测试执行一个子集。您看到的值是 100 次运行的平均时间?链接中接受的答案得出了相同的结论。 O(1) 和 O(n)。我不明白你的意思。我会认为x[n] 只是将 n 的偏移量添加到向量的第一个地址的指针地址,因此 O(1)。
    • @SimonO101 x[letters]for (letter in letters) x[letter] 不同 - 访问可能在一个 O(n) 中,但在另一个中可能是 O(1)。提取单个值的基准测试并不是非常现实,因为您通常会按许多值进行子集化 - 而且您无法通过单个值的子集化推断性能。
    • @hadley 听起来很有趣。但这是否意味着对于 for 循环中的每次访问,x[letter] 都比出现在循环外时要快?你能详细说明一下吗?
    猜你喜欢
    • 2014-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-02
    • 2011-03-24
    相关资源
    最近更新 更多