【问题标题】:Find the row that most frequently contains the largest value in a given column查找给定列中最常包含最大值的行
【发布时间】:2017-06-14 10:54:52
【问题描述】:

对于一个可能不太理想的标题表示歉意 - 我似乎想不出更好的标题。

假设我有一个像这样的 3x5 矩阵:

test.df <- matrix(rep(1:5, 3), nrow = 3)
test.df
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    4    2    5    3
[2,]    2    5    3    1    4
[3,]    3    1    4    2    5

我想返回每列中最常具有最大值的行的索引。我可以像这样结合which.maxapplytable 来做到这一点:

which.max(
    table(
        apply(test.df, 2, which.max)
        )
    )

首先我将which.max 应用于每一列:

apply(test.df, 2, which.max)
[1] 3 2 3 1 3

然后我将table 应用于结果向量,并计算给定行被发现具有最大值的次数。

table(
    apply(test.df, 2, which.max)
)
1 2 3 
1 1 3 

最后,我再次使用which.max 来获取值最多的行的索引。

不幸的是,我需要对大约 20000 个矩阵执行上述操作,其中一些矩阵可能包含数千行。所以我想知道是否有更快和/或更优雅的解决方案。最好是利用 R 中矩阵运算的力量。

非常感谢!

【问题讨论】:

    标签: r matrix


    【解决方案1】:

    这个使用rowSums 的解决方案似乎提供了相当不错的加速:

    test.df <- matrix(rep(1:5, 3), nrow = 3)
    
    original = function(m) {
        which.max(
            table(
                apply(m, 2, which.max)
            )
        )
    }
    
    row_sums = function(m) {
        which.max(rowSums(apply(m, 2, function(x) {x == max(x)})))
    }
    
    library(microbenchmark)
    
    microbenchmark(original(test.df), row_sums(test.df))
    

    计时结果:

    Unit: microseconds
                  expr    min      lq      mean median     uq      max neval
     original(test.df) 86.725 91.6320 107.19399 92.513 94.462 1376.445   100
     row_sums(test.df) 26.698 28.0895  54.30694 29.741 32.443 2378.536   100
    

    【讨论】:

    • 运行基准测试是个好主意,但由于矩阵如此之小,结果不可靠/信息不丰富
    • 是的,我在最初的测试中确实将它增加到了 100 行,它似乎能坚持下去,但如果增加到 10000+,这似乎最终会比原来的要慢。
    • 谢谢马吕斯。我自己想到了rowSums,但不是这样。这是一个相当大的加速。至少大约 1000 行。谢谢!
    • 在我的简短基准测试中,我发现 OP 的方法最快,然后是我的(现已删除),然后是 Marius',数据大小约为 100k 行和 100 列
    【解决方案2】:

    您可以避免在基础 R 中通过 max.col 循环列(即 apply):

    which.max(table(max.col(t(test.df))))
    

    【讨论】:

    • which.max(tabulate(max.col(t(test.df))))
    • 感谢您的建议!根据 1000x15 矩阵的基准,这种方法比原始版本或 Marius 建议的改进运行得更快。我也喜欢tabulate 的建议。不幸的是,表函数只报告它看到的案例。所以代码必须更加混乱才能确保返回正确的索引。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-07-04
    • 1970-01-01
    • 1970-01-01
    • 2015-03-15
    • 2010-10-19
    • 1970-01-01
    • 2018-01-09
    相关资源
    最近更新 更多