从Pandas DataFrame创建NetworkX图

4

我刚开始学习编码,并尝试理解NetworkX的工作原理。我有一个带有文档和主题列的Pandas DataFrame。 topics列指示每个文档(行)中是否存在特定主题。

df = pd.DataFrame({'DOC': ['Doc_A', 'Doc_B', 'Doc_C', 'Doc_D', 'Doc_E'], 'topic_A': [0,0,1,0,0], 'topic_B': [1,0,0,1,0], 'topic_C': [0,1,1,1,0]})

    DOC     topic_A topic_B topic_C
0   Doc_A   0       1       0
1   Doc_B   0       0       1
2   Doc_C   1       0       1
3   Doc_D   0       1       1
4   Doc_E   0       0       0

我希望做的是创建这样的网络:
1) 文档是节点,主题是边(无权重),同一节点可能有多个边。
2) 文档是节点,主题是边,但不再是多个边,而是根据它们共享的主题数量赋予不同的权重。
如何实现这个想法?我是否想得正确呢?

你有一个只有一个节点的边缘(Topic_A)。边缘应该有两个节点。我认为你的数据框生成的网络无效。不过,我的想法可能是错误的。 - Scott Boston
我知道,但我不明白如何从这些出现中创建边缘! - SamWachtman
在图论中,边仅存在于两个节点之间。因此,您不能有一个称为边的主题,它至少没有两个文档。 - Scott Boston
我认为这可能是一个X-Y 问题 - Scott Boston
谢谢Scott,我明白你的意思。我会尝试重新表述:我该如何创建一张表格,其中文档中主题的共现关系被表示为边缘? - SamWachtman
1个回答

3
这是如何构建一个网络,其中文档中主题的共现表示为边缘的方法:
首先,将DOC设置为索引并堆叠数据帧。您将获得表格的线性表示:
stacked = df.set_index('DOC').stack()
#DOC           
#Doc_A  topic_A    0
#       topic_B    1
#       topic_C    0
#...

当然,您只需要具有1的行,因为1表示主题和文档之间存在连接:
stacked = stacked[stacked==1]

这个表的多重索引实际上是边缘列表:
edges = stacked.index.tolist()
#[('Doc_A', 'topic_B'), ('Doc_B', 'topic_C'), ('Doc_C', 'topic_A'),
# ('Doc_C', 'topic_C'), ('Doc_D', 'topic_B'), ('Doc_D', 'topic_C')]

让我们把它做成一个网络。新的图是二分图。你可以将其投影以保留主题但丢弃文档 - 或者反过来:
G = nx.Graph(edges)
Gp = nx.bipartite.project(G,df.set_index('DOC').columns)
# or
# nx.bipartite.project(G,df.set_index('DOC').index)
Gp.edges()
#EdgeView([('topic_A', 'topic_C'), ('topic_B', 'topic_C')])

紧接着是一个毫不掩饰的自我推销的链接

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