在 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 是文本,而距离是数字,并且所需的输出是一个矩阵,因为速度是关键。
以下是一些基本 R 选项
xtabsv <- 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.distv <- 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)
matrixv <- 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)