从数据框创建邻接矩阵

3

我正在尝试将边列表转换为邻接矩阵。

以下是样本数据:

#Sample Data
User<-c("1","1","2","3","4")  
v1 <- c("b", "b", "a", "d", "c")
v2 <- c("c", "d", "c", "a", "a")
v3 <- c(0, 0, "d", 0, "b")
v4 <- c(0, 0, 0, 0, 0)
v5 <- c(0, 0, 0, 0, 0)

my_data<-data.frame(User, v1, v2, v3, v4, v5)
my_data

如果您运行此代码,您将得到以下输出:
  User v1 v2 v3 v4 v5
    1  b  c  0  0  0
    1  b  d  0  0  0
    2  a  c  d  0  0
    3  d  a  0  0  0
    4  c  a  b  0  0

使用这些数据,我想要创建一个类似于下面的邻接矩阵:

   a  b  c  d
a  0  0  2  2        
b  0  0  1  1
c  2  1  0  1  
d  2  1  1  0 

基本上,所需的输出显示样本数据框中v1~v5列中每个对出现的次数计数。

我尝试使用dils库中的AdjacencyFromEdgelist函数,也尝试通过循环遍历数据框来创建一个包含NAs的矩阵壳并填充矩阵。

然而,我都无法使这两种方法起作用。


“c-a”是否被视为“a-c”?因为我注意到在无向图中,“b-c”和“c-b”被视为相同,但是对于“a”和“c”并非如此。 - Anoushiravan R
1
哦 - 错误。它应该被视为相同的。 - Yun Tae Hwang
3个回答

4

我认为这可能接近你所想要的内容。在有超过2个顶点的行中,我考虑了每一对现有的顶点:

library(igraph)

do.call(rbind, my_data[-1] |>
          apply(1, \(x) x[x != 0]) |>
          lapply(\(x) t(combn(x, m = 2)))) |>
  graph_from_edgelist(directed = FALSE) %>%
  as_adjacency_matrix()

4 x 4 sparse Matrix of class "dgCMatrix"
  b c d a
b . 2 1 1
c 2 . 1 2
d 1 1 . 2
a 1 2 2 .

或者在基本R中不使用pip运算符:

tmp <- apply(my_data[-1], 1, function(x) x[x != 0])
tmp <- do.call(rbind, lapply(tmp, function(x) t(combn(x, m = 2))))

my_graph <- graph_from_edgelist(tmp, directed = FALSE)
adj_mat <- as_adjacency_matrix(my_graph)
adj_mat

我认为问题出在新的 R 管道操作符 |> 上。因为它将 LHS 作为 RHS 的第一个参数传递。你可以暂时将其替换为 %>%,看看解决方案是否适用于你。但我会进行编辑。 - Anoushiravan R
将 |> 替换为 %>%,仍然出现错误..."Error: unexpected input in:..." - Yun Tae Hwang
我以为你很熟悉。你应该附加 library(dplyr) - Anoushiravan R
我添加了另一种解决方案,你现在可以检查。 - Anoushiravan R

3

尝试另一种方法,无需使用combn计算所有组合。

sel <- my_data[-1] != 0
dat <- data.frame(row=row(my_data[-1])[sel], value = my_data[-1][sel])
out <- crossprod(table(dat))
diag(out) <- 0
out

#     value
#value a b c d
#    a 0 1 2 2
#    b 1 0 2 1
#    c 2 2 0 1
#    d 2 1 1 0

匹配@AnoushiravanR的结果:

adj_mat[c("a","b","c","d"), c("a","b","c","d")]
#4 x 4 sparse Matrix of class "dgCMatrix"
#  a b c d
#a . 1 2 2
#b 1 . 2 1
#c 2 2 . 1
#d 2 1 1 .

1
一个非常好的和优雅的解决方案 :) - Anoushiravan R
不错的解决方案,很有趣! - ThomasIsCoding

2

另一个 igraph 选项

do.call(
  rbind,
  combn(df, 2, setNames, nm = c("from", "to"), simplify = FALSE)
) %>%
  filter(from > 0 & to > 0) %>%
  arrange(from) %>%
  graph_from_data_frame(directed = FALSE) %>%
  get.adjacency(sparse = FALSE)

提供

  a b c d
a 0 1 2 2
b 1 0 2 1
c 2 2 0 1
d 2 1 1 0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接