从CSV文件创建Networkx图

14

我正在尝试从一个CSV文件中构建一个NetworkX社交网络图。我正在使用Networkx 2.1和Python 3。

我按照这篇帖子的步骤进行操作,但是没有成功,因为我不断收到以下错误:

AttributeError: 'list' object has no attribute 'decode'

我的目标是使较大的权重显示更粗的边缘。

以下是我迄今为止的代码:

import networkx as nx
import csv

Data  = open('testest.csv', "r", encoding='utf8')
read = csv.reader(Data)
Graphtype=nx.Graph()   # use net.Graph() for undirected graph

G = nx.read_edgelist(read, create_using=Graphtype, nodetype=int, data=(('weight',float),))

for x in G.nodes():
      print ("Node:", x, "has total #degree:",G.degree(x), " , In_degree: ", G.out_degree(x)," and out_degree: ", G.in_degree(x))   
for u,v in G.edges():
      print ("Weight of Edge ("+str(u)+","+str(v)+")", G.get_edge_data(u,v))

nx.draw(G)
plt.show()

有没有更简单的方法来解决这个问题?数据相对来说比较简单。

谢谢你的帮助!


1
我们无法在没有 MCVE 的情况下重现错误。您能上传 csv 文件或其中的一部分吗? - ducminh
谢谢您的提示,已添加到Github。@ducminh我是Stack Overflow的新手。 - Melissa
1个回答

14
您正在错误使用函数read_edgelist。根据文档,每行需要被解析为一个字符串,而csv.reader将输入文件中的每一行解析为字符串列表(例如,202,237,1 -> ['202','237','1'])。因此,由于read_edgelist试图解析由csv.reader提供的列表,而它们应该是字符串,所以会引发AttributeError
我们可以在不使用csv模块的情况下正确解析输入文件中的图形。但是,我们仍然需要处理输入文件的第一行(标题),该行不应被解析。有两种方法。第一种方法是使用next跳过第一行:
Data = open('test.csv', "r")
next(Data, None)  # skip the first line in the input file
Graphtype = nx.Graph()

G = nx.parse_edgelist(Data, delimiter=',', create_using=Graphtype,
                      nodetype=int, data=(('weight', float),))

第二种方法有点“hacky”:因为第一行以target开头,我们将字符t标记为输入文件中注释的开始。
Data = open('test.csv', "r")
Graphtype = nx.Graph()

G = nx.parse_edgelist(Data, comments='t', delimiter=',', create_using=Graphtype,
                      nodetype=int, data=(('weight', float),))

在两种方法中,我们必须使用parse_edgelist而不是read_edgelist,因为输入文件使用\r作为换行符。要使用read_edgelist,需要以二进制模式打开文件,只有当换行符为\r\n\n时才会分割每一行。因此,带有\r换行符的输入文件无法正确分割成行,也无法正确解析。
另外,由于您想要查找入度和出度,所以图应该使用DiGraph创建,而不是Graph

编辑

关键点在于跳过输入文件中的标题。我们可以通过首先将输入文件读入pandas.DataFrame,然后将其转换为图来实现此目的。
import networkx as nx
import pandas as pd

df = pd.read_csv('test.csv')
Graphtype = nx.Graph()
G = nx.from_pandas_edgelist(df, edge_attr='weight', create_using=Graphtype)

谢谢你的帮助 @ducminh!!! 如果我选择仅从数据中绘制某些节点而不是所有节点,会发生什么变化?我之所以问这个问题,是因为第二种方法解析边缘列表的规格(这是我发现最好的方法!)。 (例如:如果您只想查看节点6、240和282以及它们连接到的节点)。 - Melissa
@Melissa 我能想到两种方法:一种是先过滤DataFrame的行,然后从过滤后的数据创建图形;另一种是先创建完整的图形,然后取子图。第一种方法会更有效率。 - ducminh

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