我有一个以下形式的矩阵:
adj <- matrix(c(2, 3, 335, 337, 6, 7, 10,
1, 1, 1, 1, 3, 3, 3), nrow = 7)
adj
[,1] [,2]
[1,] 2 1
[2,] 3 1
[3,] 335 1
[4,] 337 1
[5,] 6 3
[6,] 7 3
[7,] 10 3
矩阵首先按列2排序,然后按列1排序。 我想将其转换为表格的(邻接)列表:
[[1]] 2 3 335 337
[[2]] integer(0)
[[3]] 6 7 10
我最近刚接触R(和Stack Overflow)并且知道这个选择 实施可能会大大提高计算速度。 我执行此任务的第一个天真实现是
adj <- lapply(1:(tail(adj, 1)[2]), function(x) {
as.integer(adj[which(adj[,2] == x), 1])
})
遗憾的是,没有利用第2列被排序的知识,当'adj'是一个大矩阵(更具体地,68.2 Mb)时似乎相当慢,而我能够在一个分数中完全构建原始矩阵几秒钟。
因此,我想知道什么是实现此类代码的更“友好”的方式。 (到目前为止,我一直避免使用循环。)
答案 0 :(得分:3)
将第二列转换为具有所有级别的因子fac
,然后将第一列拆分为该列。 (如果adj[, 2]
未排序,则使用min(adj[, 2])
和max(adj[, 2])
作为seq
的参数。)
nr <- nrow(adj)
fac <- factor(adj[, 2], levels = seq(adj[1, 2], adj[nr, 2]))
split(adj[, 1], fac)
,并提供:
$`1`
[1] 2 3 335 337
$`2`
numeric(0)
$`3`
[1] 6 7 10
注意,如果你想要整数首先将adj转换为整数,然后运行上面的代码。
mode(adj) <- "integer"
答案 1 :(得分:1)
base R
选项是split
。使用元素list
创建长度为3的integer(0)
,然后根据第二列将第一列的split
值分配给在'adj'第二列中找到的元素
lst <- setNames(rep(list(integer(0)), 3), 1:3)
lst[unique(adj[,2])] <- split(adj[,1], adj[,2])
lst
#$`1`
#[1] 2 3 335 337
#$`2`
#integer(0)
#$`3`
#[1] 6 7 10