1

假设我有以下数据集:

name1 <- c("John", "Mary", "Anne", "Joe", "David")
name2 <- c("Mary", "John", "Linda", "David", "Joe")

df <- data.frame(name1, name2)

> df
  name1 name2
1  John  Mary
2  Mary  John
3  Anne Linda
4   Joe David
5 David   Joe

name3 <- c("Kate", "Kate", "Kate", "Roger", "Roger", "Patty", "Patty")
name4 <- c("Mary", "John", "Bob", "David", "Joe", "Anne", "Linda")

df2 <- data.frame(name3, name4)

> df2
  name3 name4
1  Kate  Mary
2  Kate  John
3  Kate   Bob
4 Roger David
5 Roger   Joe
6 Patty  Anne
7 Patty Linda

当名称相互配对时,它们被视为“集合”。所以“约翰和玛丽”是一对,因为还有“玛丽和约翰”。

我想看看 df 中的每一对(John & Mary 和 Joe & David)有多少次与 df2 中的一个人连接。所以在这个玩具示例中,John 和 Mary 都与 Kate 相关联,而 David 和 Joe 都与 Roger 相关联。如果 John 和 Mary 也与 Roger 有关联,那么他们将是一个人两次的集合,因此在 No. of times 下,它将是“2”。

对于当前的 dfs,我想要一个显示:

Pair              No. of times
John – Mary       1
Roger – Joe       1

有一些社交网络包可以提供这些人如何连接的视觉效果,但我只是在寻找一个显示计数数量的简单表格。

4

1 回答 1

1

这是一个使用igraph包的方法。首先,我们从主 data.frame 创建一个图形,保持在“集合”上(那些顶点由多个节点边缘连接)。然后我们通过给它们“main”的边缘属性来标记那些是我们感兴趣的。然后,我们将这些数据与其余数据连接起来。

gg1 <- graph_from_data_frame(df, directed = FALSE)
gg1 <- delete_edges(gg1, which(!which_multiple(gg1)))
E(gg1)$main <- TRUE

gg2 <- graph_from_data_frame(df2, directed = FALSE)

ggfull <- union(gg1, gg2)

# (optional) preview results
E(ggfull)$color <- ifelse(!is.na(E(ggfull)$main), "red", "grey")
plot(ggfull)

现在这是一个辅助函数,它将遍历图形并找到所有“三角形”,其中一条边来自“主”集合。

find_main_trios <- function(g) {
  tricnt <- numeric(gsize(g))
  triset <- triangles(g)
  for(i in seq(1, length(triset), by=3)) {
    edges <- c(
      E(g)[triset[i]%--%triset[i+1]], 
      E(g)[triset[i+1]%--%triset[i+2]],
      E(g)[triset[i]%--%triset[i+2]]
    )
    for (edge in edges)
      if (!is.na(E(g)[edge]$main)) {
        tricnt[edge]  = tricnt[edge] + 1
      }
  }
  do.call("rbind", lapply(which(tricnt>0), function(i) {
    names <- V(g)[inc(i)]$name
    data.frame(name1=names[1], name2=names[2], count=tricnt[i], edgeid=i)
  }))
}

大部分工作是由triangles()查找所有相互连接的三个节点的集合的函数完成的。然后,我们需要确保每个三角形都包含我们感兴趣的第一个 data.frame 中的一个集合。函数的最后一个投标只是将所有内容整理到一个 data.frame 中。所以当我们运行它时,我们得到

find_main_trios(ggfull)
#   name1 name2 count edgeid
# 1   Joe David     1      5
# 2  John  Mary     1      9

这给出了您所追求的摘要。

于 2021-10-28T17:06:23.830 回答