2016-03-08 52 views
1

比方说,我们有这样的矩阵:的R - n个最小值的矩阵的上三角获取dimnames

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

我会做

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选择前三行。

即使var name没有排序,但没有测试,我认为步骤3仍然有效。


类似dplyr代码:

library(dplyr) 

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