【问题标题】:Get max value from each point in matrix从矩阵中的每个点获取最大值
【发布时间】:2015-09-29 21:18:30
【问题描述】:

我有 2 个数据框

a = c(1,1,3)
b = c(7,2,1)
c = c(2,4,2)

d1 = cbind(a,b,c)

d = c(2,1,6)
e = c(1,4,2)
f = c(4,8,4)

d2 = cbind(d,e,f)

如何轻松获取每个点的最大值数据框

_fun(d1,d2)

     a b c
[1,] 2 7 4
[2,] 1 4 8
[3,] 6 2 4

我可以使用循环来做到这一点,但对于大数据帧来说它非常慢。

谢谢!

【问题讨论】:

    标签: r matrix max


    【解决方案1】:

    我们可以将数据集保存在list 中,并使用do.callf 作为pmax

    do.call(pmax, list(d1, d2))
    #     a b c
    #[1,] 2 7 4
    #[2,] 1 4 8
    #[3,] 6 2 4
    

    或者直接使用pmax

    pmax(d1, d2)
    

    编辑:基于@nicola 的 cmets。

    使用pmax.int 可能会更快,但转换回matrix 可能会更慢。

    matrix(pmax.int(d1, d2), dim(d1))
    

    基准测试

    set.seed(24)
    m1 <- matrix(sample(0:9, 5000*5000, replace=TRUE), ncol=5000)
    set.seed(48)
    m2 <- matrix(sample(0:9, 5000*5000, replace=TRUE), ncol=5000)
    akrun1 <- function() pmax(m1, m2)
    akrun2 <- function() matrix(pmax.int(m1, m2), dim(m1))
    colonel <- function() ifelse(m1 > m2, m1, m2)
    system.time(akrun1())
    #   user  system elapsed 
    #  0.850   0.033   0.885 
    system.time(akrun2())
    #   user  system elapsed 
    #  1.090   0.021   1.114 
    
    system.time(colonel())
    #   user  system elapsed 
    #  5.049   0.336   5.395 
    

    【讨论】:

    • 不需要任何Reduce。只需pmax(d1,d2) 即可。此外,如果要比较的元素多于两个,则应使用do.call 而不是Reduce(更慢)。 do.call(pmax, list(d1, d2)) 好多了。
    • @nicola 谢谢,当您发表评论时,我正在更改为pmax(d1, d2)
    • @ColonelBeauvel 它看起来很快,但我不确定创建一个额外的对象是否会为大数据集节省内存
    【解决方案2】:

    或者简单地使用矢量化的ifelse

    ifelse(d1>d2, d1, d2)
    #     a b c
    #[1,] 2 7 4
    #[2,] 1 4 8
    #[3,] 6 2 4
    

    或者自建函数(只是为了测试速度):

    func = function(d1, d2) {m=d2;m[d1>d2]=d1[d1>d2];m}
    

    还有一些基准测试,最后自建函数似乎是最快的(但@Akrun 的解决方案足够快,应该也可以解决您的问题):

    #> d2 = matrix(sample(9000000), ncol=3000)
    #> d1 = matrix(sample(9000000), ncol=3000)
    #> system.time(ifelse(d1>d2, d1, d2))
    #   user  system elapsed 
    #   2.13    0.37    2.49 
    #> system.time(matrix(pmax.int(d1, d2), dim(d1)))
    #   user  system elapsed 
    #   0.44    0.00    0.43 
    #> system.time(pmax(d1, d2))
    #   user  system elapsed 
    #   0.41    0.02    0.42 
    #> system.time(do.call(pmax, list(d1, d2)))
    #   user  system elapsed 
    #   0.34    0.01    0.36 
    #> system.time(func(d1,d2))
    #   user  system elapsed 
    #   0.32    0.03    0.36 
    

    【讨论】:

    • 事实上我需要使用超过 2 个 df 来获得最大值,但感谢您的帮助
    【解决方案3】:

    您也可以使用abind 创建一个数组,然后像这样使用apply

    library(abind)
    
    d3 <- abind(d1, d2, along = 3)
    apply(d3, c(1, 2), max)
    

    【讨论】:

    • 我在帖子中使用大数据集尝试了这种方法。它似乎很慢,即 system.time 为 306
    • 是的,对于一个非常大的数据集,我希望这种方法低于标准
    猜你喜欢
    • 1970-01-01
    • 2013-07-31
    • 1970-01-01
    • 1970-01-01
    • 2016-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多