我们假设我们有一个这样的矩阵:
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"
是否有更简单的方法,既节省内存又节省时间?
答案 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
工作原理:
melt
会将您的矩阵转换为长格式(类型?melt.matrix
)。setDT
转换为data.table(有关语法,请参阅intro vignettes。)as.integer(Var2) > as.integer(Var1)
获得上三角。order(value)
按升序对长格式数据进行排序。1:3
选择前三行。我认为即使var命名没有被排序,但是没有测试它,步骤3也能工作。
类似的dplyr代码:
library(dplyr)
melt(m) %>% filter(as.integer(Var2) > as.integer(Var1)) %>% arrange(value) %>% slice(1:3)