我有一个矩阵表,其中行表示地点,列表示特定岩石的存在/不存在。
>Mat
A B C D E F G
Aiz 1 0 0 0 0 0 0
Aren 0 1 1 0 1 0 0
Atx 0 0 1 0 1 0 0
Berr 1 1 0 0 0 1 0
Bra 0 0 0 0 0 1 0
Bur 0 1 0 0 1 0 0
Cab 1 0 1 1 1 0 0
正如您所看到的,有些行在某些列中具有相同的元素,例如。 Aiz
行和 Berr
行在 A
列中共享,这表明它们在我的示例中共享同一 block 岩石。
从这个矩阵中,我想构造一个无向图,其中节点是站点(行名),链接是列元素的份额。
所以,基本上,我需要将此矩阵转换为以下样式的 data.frame:
>DF
siteA siteB weight
1 Aiz Berr 1
2 Aiz Cab 1
3 Aren Atxos 2
4 Aren Berr 1
5 Aren Bur 2
6 Aren Cab 1
7 Atx Bur 1
...
其中每行标识共享同一 block 岩石的两个站点(存在于原始Mat
的同一列中),并且具有权重
列,表示两者都使用的岩石数量网站有共同点。
因此,通过一系列嵌套的 for 循环
和 if
条件,我设法接近 DF
矩阵,尽管我的DF
具有重复结果的行,例如:
> df_links
siteA siteB weight
1 Aiz Berr 1
2 Aiz Cab 1
3 Aren Atxos 2
4 Berr Aiz 1
5 Atxos Aren 2
您看到的位置,例如:第 1 行
和 第 4 行
(第 3 行
和 第 5 行
相同) ) 网站栏共享相同的元素。由于这是一个无向图,因此具有 Aiz-Berr 或 Ber-Aiz 意味着相同,因此我只需要其中一行。
问题 1:因此,我尝试使用 tidyverse
解决重复问题,但似乎没有效果。最好的情况下,我只会删除其中的一个重复行,而不是全部。所以,我的问题是,有什么办法可以做到这一点吗?仅保留具有相同元素 [i,j]
的行之一,无论顺序如何?
问题 2:这可能有点麻烦,所以排在第二位。尽管我的代码可以工作(直到上面第一季度指出的问题),但它看起来并不是最漂亮的。是一个矩阵到 data.frames 到 data.frames 的序列,带有 for 循环
和条件。
是否有一个更简洁的版本可以从原始的 Mat
转换为所需的 DF
?我不太熟悉 sapply 和整个系列,所以我使用了循环。有更快、更好看的解决方案吗?
最佳答案
使用 purrr 包可以解决该问题。
# reproduce input
mat <- matrix(
data = c(1,0,0,0,0,0,0,
0,1,1,0,1,0,0,
0,0,1,0,1,0,0,
1,1,0,0,0,1,0,
0,0,0,0,0,1,0,
0,1,0,0,1,0,0,
1,0,1,1,1,0,0), nrow = 7, ncol = 7)
colnames(mat) <- LETTERS[1:7]
rownames(mat) <- c("Aiz", "Aren", "Atx", "Berr", "Bra", "Bur", "Cab")
# convert to dataframe
df <- mat %>%
dplyr::as_tibble() %>%
dplyr::bind_cols(
tibble::tibble(Names = rownames(mat)))
# calculate the connections
purrr::map_df(df$Names, function(x){
output <-purrr::map_df(df$Names, function(y){
if(x >= y) return(tibble::tibble()) # avoid double counting
tibble::tibble(
siteA = x,
siteB = y,
weight = sum(as.integer(df[df$Names==x,1:7]) & as.integer(df[df$Names==y,1:7])))
})
})
祝你好运
关于r - 将存在/不存在矩阵转换为顶点连接的 Data.frame。 (删除具有eeuqal无序值的重复行),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67588472/