【图论】基于数据集生成的演员合作网络图的简单分析(结果有彩蛋)

发布时间:2025-05-14 00:00

刚刚做完图论课的大作业,从中收获了很多东西,最终结果也很有意思。

背景:
2005年的时候开展了一次图像绘制会议(Graph Drawing conference),期间展示了用互联网电影资料库(IMDb)提供的数据集生成的演员合作网络图。即把每个演员看成一个顶点,如果两个演员在1995年至2005年之间合作拍摄过两次以上的电影,则将他们用一条无向边连接起来,再将不同类型的电影用不同颜色加以区分,从而得出了下面这幅“演员合作网络图”(很是复杂啊!)。

当然,为了降低难度,提供给我们使用的是两个经过简化过的数据集:

1.imdb_actor_edges.tsv 2.imdb_actors_key.tsv 12

第一个数据集里面包含了演员1的ID和演员2的ID,以及它们之间在十年内合作拍摄过的电影的数量num_movies。


这个数据集有多庞大呢?
我用Excel打开并排序之后发现其中总共有28万余条这种关联数据。


第二个数据集里面包含了每个演员的信息,包括ID、姓名name、十年间拍摄过的电影的数量movies_95_04、主要参演电影类型main_genre以及每种类型的具体数量。

再用Excel打开之后发现总共有一万七千多的演员数据。

至此,我对这项工程的数据规模有了初步的了解:

我需要处理的是一个含有17000余个顶点,280000余条边的无向图!

虽然心中有一万头奔腾的羊驼,我还是硬着头皮查看了这个project的要求:

计算每个节点的度数,输出度数最大的前20个节点及其度数(如果末位有并列,则全部输出,即:最终输出节点数可多于20) 计算节点度数的分布并作图:横坐标为度数degrees,纵坐标为拥有该度数的节点数nodes。 [加分项]针对上述数据集,选择任何你感兴趣的点进行分析。

还好,还好,原来只是写个程序啊 (喝口快乐水压压惊。。。。。)

那么问题来了:怎么写???

我:emmmm…emmmmm…

在经过(询)(问)(大)(佬)之后,

得到了如下Python代码:

# 这段代码需要满足以下两个要求: # 1.计算每个节点的度数,输出度数最大的前20个节点及其度数(允许并列存在) # 2.计算节点度数的分布并作出一个线性图表:其中x轴代表了度数(合作过的次数),y轴代表了节点数(演员数) edge = {"actor1": None, "actor2": None, "num_movies": None} # 将边edge表示成字典型,其有三个键值对,分别代表边的三个属性 node = {"id": None, "name": None, "movies_95_04": None, "main_genre": None, "genres": None} # 将节点node表示成字典型,其有五个键值对,分别代表节点(演员)的五个属性 node_xy = {"degree": None, "node_number": None} # 将节点度数和节点数表示成字典型,其中degree在图像中为x轴,node_number在图像中为y轴 # 定义一个将边edge的数据储存在数组中的函数read_edge,实现读取录入的操作 def read_edge(file): edge_list = list() with open(file, 'r', encoding='utf-8') as f: # 以只读模式,用utf-8编码方式打开文件 line = f.readline() while line: line = f.readline() if line: a = line.split('\t') edge_list.append({"actor1": a[0], "actor2": a[1], "num_movies": a[2]}) return edge_list # 定义一个将节点node的数据储存在集合中的函数read_node,实现读取录入的操作 def read_node(file): nodes = dict() with open(file, 'r', encoding='utf-8') as f: # 以只读模式、用utf-8编码方式打开文件 line = f.readline() while line: line = f.readline() if line: a = line.split('\t') nodes[a[0]] = {"name": a[1], "movies_95_04": a[2], "main_genre": a[3], "genres": a[4], "degree": 0} return nodes # 定义将所得度数进行排序的函数sort def sort(nodes: dict): node_degree = list() for node_id, value in nodes.items(): node_degree.append({'ID': node_id, 'degree': value['degree']}) node_degree.sort(key=lambda node : node['degree'], reverse=True) t = list() num = 0 for n in node_degree: # 筛选出度数最大的20个节点 if num < 20: t.append(n) else: if n['degree'] == t[19]['degree'] : t.append(n) num = num + 1 return t # 计算单个点度数的函数degree def degree(e, n): for edge in e: actor1 = edge['actor1'] actor2 = edge['actor2'] n[actor1]['degree'] = n[actor1]['degree'] + 1 n[actor2]['degree'] = n[actor2]['degree'] + 1 return n # 定义计算所有点度数的函数count def count(file: dict): t = dict() for node_id, value in file.items(): degree = value['degree'] t[degree] = 0 for node_id, value in file.items(): degree = value['degree'] t[degree] = t[degree] + 1 return t # 执行脚本 if __name__ == "__main__": Edge = read_edge(r"C:\Users\86188\Desktop\project\imdb_actor_edges.tsv") # 用read_edge函数读取相应路径的文件并将数据存储在Edge中,具体路径可以灵活变更 Node = read_node(r"C:\Users\86188\Desktop\project\imdb_actors_key.tsv") # 用read_node函数读取相应路径的文件并将数据存储在Node中,具体路径可以灵活变更 temp = degree(Edge, Node) # 用count_degree函数计算每个节点的度数,并储存在temp中 MAX = sort(temp) # 用sort函数给所得度数temp进行排序,并计算出拥有最大度数的20个节点,并储存在MAX中 degree_number = count(Node) # 用count_degree_numbers函数计算每个节点的度数,并储存在degree_number中 print("\n度数最大的前20个节点的ID及其度数为:") print(MAX) # 输出度数最大的前20个节点的相应数据 x=list() y=list() for node_degree, i in degree_number.items(): x.append(node_degree) y.append(i) # 至此,我们已经得到了度数最大的前20个节点的ID以及它们对应的度数 # 它们将按照[{'node_id':'id-number', 'degree':degree-number},{...},{...}.......{...}]的格式输出 # 开始图像绘制,这里需要用到matplotlib库(已预先导入) # 需要注意的是matplotlib库对中文不太支持,容易出现显示不出来的情况,所以此图表里的文字一律使用英文 import matplotlib.pyplot as plt # 引入matplotlib库,用于绘制图像 plt.figure(figsize=(10, 6), facecolor='pink') # 定义图表属性,长10英寸,宽6英寸,背景颜色为粉色 plt.plot(x, y, color='c', linestyle='-.', marker='*') # 定义线条属性,颜色为青色,线条风格为点划线,标记点风格为星型 plt.xlabel('degree number (co-star-movie-number)') # 显示x轴的表示含义——度数(合作次数) plt.ylabel('nodes number (actors)') # 显示y轴的表示含义——节点数(演员数) plt.title('Node Degree Distribution Diagram') # 显示图表的标题 plt.show() # 将图表show出来 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117

大概思路:先把节点和边转化成字典型的数据,方便索引。之后通过两个函数来实现对数据集文件的数据导入,再提取出来各个节点的度数,然后利用排序函数对由这些度数组成的新的集合进行排序,从而筛选出度数最大的前20个节点。

结果:

可以得出度数最大的前20个节点的ID及其度数degree为: [{'ID': '162', 'degree': 784}, {'ID': '1743', 'degree': 610}, {'ID': '1754', 'degree': 599}, {'ID': '1802', 'degree': 584}, {'ID': '407', 'degree': 561}, {'ID': '164', 'degree': 555}, {'ID': '179', 'degree': 545},{'ID': '176', 'degree': 533}, {'ID': '175', 'degree': 500}, {'ID': '160', 'degree': 493}, {'ID': '127', 'degree': 490},{'ID': '1626', 'degree': 475}, {'ID': '131', 'degree': 471},{'ID': '2108', 'degree': 471}, {'ID': '163', 'degree': 463}, {'ID': '701', 'degree': 457}, {'ID': '1778', 'degree': 451}, {'ID': '177', 'degree': 450}, {'ID': '1688', 'degree': 438}, {'ID': '1804', 'degree': 428}] 1234567891011

之后,由于需要绘制图表,故需要引入第三方的matplotlib库。

得到的折线图如下:

以为这就完了?
别走,说好了有彩蛋的

我出于好奇还分析了度数最多的前20名的参演电影类型。毕竟这些演员与其他演员“合作”参演的电影实在是太多了,直觉告诉我这很不寻常,有必要分析一下!

于是我按照ID用Excel筛选出了这些演员的信息:


结果出人意料但又在情理之中:

20个演员当中除了ID为701的Hanks,Tom(清流)参演的主要类型为家庭片Family,其余19人参演的主要类型均为Adult。这或许也解释了他们的度数如此之多的原因。

另外,我也对我所得到的结果的正确性有了足够的信心。

网址:【图论】基于数据集生成的演员合作网络图的简单分析(结果有彩蛋) https://mxgxt.com/news/view/1175671

相关内容

基于Python的社交网络分析与图论算法实践
基于智能合约的娱乐网络数据分析平台BETER介绍
社交网络分析的基本原理以及图数据库在社交网络分析中的应用
基于社交网络数据的行为分析研究
基于数据挖掘的社交网络分析与研究
大规模网络结构数据分析与空间自回归模型|第1章 网络数据的定义及相关指标(2)
掌握ppt销售数据分析图表制作教程,让数据可视化更简单有效
[参考]基于数据挖掘的校园社交网络用户行为分析
社交数据分析软件(社交网络数据分析系统)
帐号网红数据分析图片怎么做

随便看看