【问题标题】:Why there are missing nodes after graph intersection - NetworkX, igraph, python and r为什么图形交集后缺少节点 - NetworkX、igraph、python 和 r
【发布时间】:2023-11-12 08:47:02
【问题描述】:

我在尝试获取两个网络/图表之间的交集时遇到了一些奇怪的事情。当我检查生成的交叉点时发现缺少节点,我希望了解为什么会发生这种情况。

最初我正在使用 python 3.5.2 / pandas 0.17.1。在 Linux Mint 18 上,重现问题的数据集和代码在链接上: Dataset and code

两个表(Test_01.ncol 和 Test_02.ncol 附在链接中)都是边列表。

首先,我尝试使用 pandas 获取两个图形表的交集,并使用合并功能:

import pandas as pd

# Load graphs
test_01 = pd.read_csv("Test_01.ncol",sep=" ") # Load Net 1
test_02 = pd.read_csv("Test_02.ncol",sep=" ") # Load Net 2
pandas_intersect = pd.merge(test_01, test_02, how='inner', on=['i1', 'i2']) # Intersection by column

pandas_nodes = len(set(pandas_intersect['i1'].tolist() + pandas_intersect['i2'].tolist())) # Store the number of nodes

然后为了检查合并是否没有问题,我将结果节点数与 NetworkX 交集的结果节点数进行了比较,如下所示:

# Now test with NetworkX
import networkx as nx
n1 = nx.from_pandas_dataframe(test_01, source="i1", target="i2") # Transform net 1 in NetworkX Graph
n2 = nx.from_pandas_dataframe(test_02, source="i1", target="i2") # Transform net 2 in NetworkX Graph
fn = nx.intersection(n1,n2)  # NetworkX Intersection

networkx_nodes = len(fn.nodes()) # Store the number of nodes

# The number of nodes are different!!!
pandas_nodes == networkx_nodes

我认为这可能与节点顺序有关,这在所附表格中不是规范的,但即使我将两个数据集按规范顺序放置,也会缺少节点。

我的下一个假设是它可能是 Pandas 或 NetworkX 中的错误,所以我在 R(3.3.2 版)和 igraph(1.0.1 版)中尝试:

library("igraph")

# Read Tables
g1 <- read.table("Test_01.ncol",header=TRUE)
g2 <- read.table("Test_02.ncol",header=TRUE)

# Transform Tables in Graphs
g1 <- graph_from_data_frame(g1, directed=FALSE)
g2 <- graph_from_data_frame(g2, directed=FALSE)

# Create igraph interssection
gi <- graph.intersection(g1,g2)

# Save graph intersection
write.graph(gi,"Test_igraph_intersection.ncol", format="ncol")

# Reload graph intersection
gi_r <- read.graph("Test_igraph_intersection.ncol",format="ncol")

# Prepare result summary
Methods <- c("igraph_intersection","pandas_table_intersection")
Vertex_counts <- c(vcount(gi),vcount(gi_r))
Edge_counts <- c(ecount(gi),ecount(gi_r))

# Create Summary Table
info_data = data.frame(Methods, Vertex_counts, Edge_counts)
colnames(info_data) <- c("Method","Vertices","Edges")

# Check info_data
info_data

但是当我查看 info_data 时,结果是一样的。

我知道节点的数量可能会因为交集过程而减少,但是为什么在我在 python 上再次将其转换为表格格式并保存文件然后用 igraph 再次加载它之后会发生这种情况?还是我做错了什么?

如果有人可以解释 python 或 R 中发生的事情,我很感激。我真的需要了解为什么会发生这种情况,以及我是否可以信任这些交叉点来继续我的工作。

【问题讨论】:

    标签: python r pandas igraph networkx


    【解决方案1】:

    原因是图是无向的。 intersectionigraphnetworkx 中将 I--J 领带和 J--I 领带视为等效。 panda.intersection 只会处理完全匹配(即数据框 A 中的第 1 列匹配数据框 B 中的第 1 列数据框 A 中的第 2 列匹配数据框 B 中的第 3 列)。

    library(igraph); library(dplyr)
    set.seed(1034)
    g1 <- sample_gnp(20, 0.25, directed = F)
    set.seed(1646)
    g2 <- sample_gnp(20, 0.25, directed = F)
    V(g1)$name <- sample(LETTERS, 20)
    V(g2)$name <- sample(LETTERS, 20)
    
    g1_el <- as.data.frame(as_edgelist(g1), stringsAsFactors = F)
    g2_el <- as.data.frame(as_edgelist(g2), stringsAsFactors = F)
    g1g2_inter <- as.data.frame(as_edgelist(intersection(g1,g2)))
    ij <- inner_join(g1_el, g2_el)
    

    此时,两个数据框显示的节点数不同:

    > g1g2_inter
       V1 V2
    1   X  E
    2   J  Y
    3   N  J
    4   O  F
    5   H  Y
    6   T  J
    7   K  N
    8   K  T
    9   P  F
    10  Q  N
    
    > ij
      V1 V2
    1  T  J
    2  N  J
    3  J  Y
    4  X  E
    

    我们可以通过颠倒一个数据帧中列的顺序来使数据帧相等,再次使用inner_join。这得到了以前错过的 J--I 关系。然后full_join到两个部分交叉点:

    g1g2_fj <- g1_el %>% 
          rename(V1 = V2, V2 = V1) #reverse the column order %>% 
          inner_join(., g2_el) %>% rename(V1 = V2, V2 = V1) %>% 
          full_join(., ij) %>%  #join with other 'partial' intersection 
          arrange(V1, V2)
    

    现在,igraph 交集匹配完全连接的部分交集:

    > g1g2_inter[order(g1g2_inter[,1]),] == g1g2_fj
         V1   V2
    5  TRUE TRUE
    2  TRUE TRUE
    7  TRUE TRUE
    8  TRUE TRUE
    3  TRUE TRUE
    4  TRUE TRUE
    9  TRUE TRUE
    10 TRUE TRUE
    6  TRUE TRUE
    1  TRUE TRUE
    

    本质上,是的,您可以信任networkxigraph 的交集方法。他们正在做一些不同的事情来处理无向关系。

    【讨论】:

    • 哇!我没有意识到这是因为无向图结构。这应该在 networkx 和 igraph 的文档中,我只是认为我正在丢失节点而没有丢失边,并且结果图是一团糟,但你是对的。非常感谢!
    • 仅供参考,如果图形是定向的,那么您将不会遇到上面提到的问题——合并到两个边缘列表将具有与两者的交集相同数量的节点图表。