聚合数据框以按已排序的列值列出

时间:2018-02-20 14:01:49

标签: r

我有一个以下形式的矩阵:

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)时似乎相当慢,而我能够在一个分数中完全构建原始矩阵几秒钟。

因此,我想知道什么是实现此类代码的更“友好”的方式。 (到目前为止,我一直避免使用循环。)

2 个答案:

答案 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