R - 在矩阵的上三角形中获得n个最小值的dimnames

时间:2016-03-08 21:16:54

标签: r

我们假设我们有一个这样的矩阵:

set.seed(1)
m <- matrix(abs(rnorm(16)), ncol=4)
rownames(m) <- colnames(m) <- c('a', 'b', 'c', 'd')
m
#           a         b         c          d
# a 0.6264538 0.3295078 0.5757814 0.62124058
# b 0.1836433 0.8204684 0.3053884 2.21469989
# c 0.8356286 0.4874291 1.5117812 1.12493092
# d 1.5952808 0.7383247 0.3898432 0.04493361

是否有可能以有效的方式获取上三角形的3个最小值的维度名称?

我有以下方法:

#find the 3rd smallest value in the upper triag:
val <- m[upper.tri(m)][order(m[upper.tri(m)])[3] ]

#get the indices of values smaller than val:
ind_smallest <- arrayInd(which(upper.tri(m) & m <=val), dim(m))

cbind( colnames(m)[ind_smallest[, 1]], rownames(m)[ind_smallest[, 2]])
#      [,1] [,2]
# [1,] "a"  "b" 
# [2,] "a"  "c" 
# [3,] "b"  "c"  

是否有更简单的方法,既节省内存又节省时间?

1 个答案:

答案 0 :(得分:1)

我愿意

library(data.table)

setDT(melt(m))[as.integer(Var2) > as.integer(Var1)][order(value)][1:3]

#    Var1 Var2     value
# 1:    b    c 0.3053884
# 2:    a    b 0.3295078
# 3:    a    c 0.5757814

工作原理:

  1. melt会将您的矩阵转换为长格式(类型?melt.matrix)。
  2. setDT转换为data.table(有关语法,请参阅intro vignettes。)
  3. as.integer(Var2) > as.integer(Var1)获得上三角。
  4. order(value)按升序对长格式数据进行排序。
  5. 1:3选择前三行。
  6. 我认为即使var命名没有被排序,但是没有测试它,步骤3也能工作。

    类似的dplyr代码:

    library(dplyr)
    
    melt(m) %>% filter(as.integer(Var2) > as.integer(Var1)) %>% arrange(value) %>% slice(1:3)