将距离列表转换为距离矩阵

Emi*_*ilA 3 r distance-matrix

在 R 中,我有一个 data.frame 显示节点对之间的距离:

dl <- data.frame(
  a = c('a','a','a','b','b','c'),
  b = c('b','c','d','c','d','d'),
  dist = c(1,2,3,2,1,2)
)
Run Code Online (Sandbox Code Playgroud)

我想将其转换为距离矩阵,对角线设置为零,上三角形设置为 NA,因为距离是对称的:

dm <- data.frame(
  a = c(0,2,3,2),
  b = c(NA, 0, 2, 1),
  c = c(NA, NA, 0, 2),
  d = c(NA, NA, NA, 0),
  row.names = c('a','b','c','d')
) %>% as.matrix()
Run Code Online (Sandbox Code Playgroud)

我的真实数据非常大,所以计算效率是关键。我自己能想到的唯一解决方案涉及循环或使用igraph首先将列表转换为图形,然后将该图形转换为矩阵,考虑到我的数据大小,这并不是非常理想。输入是一个 data.frame,因为节点 ID 是文本,而距离是数字,并且所需的输出是一个矩阵,因为速度是关键。

Tho*_*ing 5

以下是一些基本 R 选项

使用xtabs

v <- unique(unlist(dl[-3]))
dl[-3] <- lapply(dl[-3], factor, levels = v)
dm <- unclass(t(xtabs(dist ~ ., dl)))
dm[upper.tri(dm)] <- NA
Run Code Online (Sandbox Code Playgroud)

这使

> dm
   a
b   a  b  c  d
  a 0 NA NA NA
  b 1  0 NA NA
  c 2  2  0 NA
  d 3  1  2  0
attr(,"call")
xtabs(formula = dist ~ ., data = dl)
Run Code Online (Sandbox Code Playgroud)

使用as.dist

v <- unique(unlist(dl[-3]))
dl[-3] <- lapply(dl[-3], factor, levels = v)
dm <- as.dist(t(xtabs(dist ~ ., dl)), diag = TRUE)
Run Code Online (Sandbox Code Playgroud)

这使

> dm
  a b c d
a 0
b 1 0
c 2 2 0  
d 3 1 2 0
Run Code Online (Sandbox Code Playgroud)

使用matrix

v <- unique(unlist(dl[-3]))
dm <- `diag<-`(matrix(NA, length(v), length(v), dimnames = list(v, v)), 0)
dm[as.matrix(rev(dl[-3]))] <- dl$dist
Run Code Online (Sandbox Code Playgroud)

这使

> dm
  a  b  c  d
a 0 NA NA NA
b 1  0 NA NA
c 2  2  0 NA
d 3  1  2  0
Run Code Online (Sandbox Code Playgroud)