如何用Python生成共享Genre的Movie Node双向Edge List?
问题:生成电影共享类型的双向边列表
我正在用Python处理themoviedb.org的数据分析项目,要构建电影的网络图——节点是电影ID,两部电影只要共享同一个类型就建立双向边。
节点数据示例
nodes = [ {'id': 315162, 'label': 'Puss in Boots: The Last Wish', 'genre_ids_1': '16', 'genre_ids_2': '28'}, {'id': 536554, 'label': 'M3GAN', 'genre_ids_1': '878', 'genre_ids_2': '27'}, {'id': 76600, 'label': 'Avatar: The Way of Water', 'genre_ids_1': '878', 'genre_ids_2': '12'}, {'id': 653851, 'label': 'Devotion', 'genre_ids_1': '10752', 'genre_ids_2': '878'}, {'id': 846433, 'label': 'The Enforcer', 'genre_ids_1': '28', 'genre_ids_2': '53'} ]
期望的双向边列表格式
source target genre_ids 315162 846433 28 846433 315162 28 76600 536554 878 76600 653851 878 536554 76600 878 ...
现有无法实现需求的代码
genres=[28,12,16,35,80,99,18,10751,14,36,27,10402,9648,10749,878,10770,53,10752,37] edges=[] nodes = [{'id': 315162, 'label': 'Puss in Boots: The Last Wish', 'genre_ids_1':'16','genre_ids_2': '28'},{'id': 536554, 'label': 'M3GAN','genre_ids_1':'878','genre_ids_2': '27'},{'id': 76600, 'label': 'Avatar: The Way of Water','genre_ids_1':'878', 'genre_ids_2': '12'},{'id': 653851, 'label': 'Devotion','genre_ids_1': '10752', 'genre_ids_2': '878'},{'id': 846433, 'label': 'The Enforcer','genre_ids_1': '28', 'genre_ids_2': '53'}] dictionary={} def get_edges(): for i in nodes: if i["genre_ids_1"] in genres: dictionary.setdefault(i['genre_ids_1'], []).append(i['label']) elif i["genre_ids_2"] in genres: dictionary.setdefault(i['genre_ids_2'], []).append(i['label']) if i["genre_ids_1"] in dictionary: if i["label"] not in dictionary[ i["genre_ids_1"]][0]: edges.append({"source":i["label"],"target":i["id"],"genre_id":dictionary[ i["genre_ids_1"]][0] }) elif i["genre_ids_2"] in dictionary: if i["label"] not in dictionary[ i["genre_ids_2"]][1]: edges.append({"source":i["label"],"target":i["id"],"genre_id":dictionary[ i["genre_ids_2"]][1] }) print(edges) get_edges()
解决方案
原代码问题分析
- 类型ID类型不匹配:节点中的类型ID是字符串,
genres列表是整数,导致匹配判断失效 - 逻辑混乱:没有正确按类型分组电影ID,也未生成双向边
- 错误使用电影标题作为边的节点,需求要求用电影ID
修改思路
- 统一类型ID的格式,将
genres转为字符串集合方便匹配 - 按类型分组所有电影ID
- 遍历每个类型下的电影ID列表,生成所有两两组合的双向边
- 按要求格式输出边列表
完整修改代码
genres = [28,12,16,35,80,99,18,10751,14,36,27,10402,9648,10749,878,10770,53,10752,37] # 转换为字符串集合,匹配节点中的类型ID格式 genre_set = set(str(g) for g in genres) nodes = [ {'id': 315162, 'label': 'Puss in Boots: The Last Wish', 'genre_ids_1': '16', 'genre_ids_2': '28'}, {'id': 536554, 'label': 'M3GAN', 'genre_ids_1': '878', 'genre_ids_2': '27'}, {'id': 76600, 'label': 'Avatar: The Way of Water', 'genre_ids_1': '878', 'genre_ids_2': '12'}, {'id': 653851, 'label': 'Devotion', 'genre_ids_1': '10752', 'genre_ids_2': '878'}, {'id': 846433, 'label': 'The Enforcer', 'genre_ids_1': '28', 'genre_ids_2': '53'} ] def get_edges(): # 按类型分组电影ID genre_to_movies = {} for movie in nodes: movie_id = movie['id'] # 收集当前电影的有效类型ID movie_genres = [] if movie['genre_ids_1'] in genre_set: movie_genres.append(movie['genre_ids_1']) if movie['genre_ids_2'] in genre_set: movie_genres.append(movie['genre_ids_2']) # 将电影ID加入对应类型的列表 for g in movie_genres: genre_to_movies.setdefault(g, []).append(movie_id) edges = [] # 生成双向边 for genre_id, movie_ids in genre_to_movies.items(): # 遍历所有两两不同的电影组合 for i in range(len(movie_ids)): for j in range(i+1, len(movie_ids)): source = movie_ids[i] target = movie_ids[j] # 添加正向和反向边 edges.append({'source': source, 'target': target, 'genre_ids': genre_id}) edges.append({'source': target, 'target': source, 'genre_ids': genre_id}) # 按格式打印边列表 print(f"{'source':<10} {'target':<15} {'genre_ids'}") for edge in edges: print(f"{edge['source']:<10} {edge['target']:<15} {edge['genre_ids']}") return edges get_edges()
代码说明
- 类型格式统一:将
genres转为字符串集合,解决类型不匹配的问题 - 类型分组:遍历每个电影,将其ID加入对应类型的分组列表
- 双向边生成:对每个类型下的电影ID,生成所有两两组合的正向和反向边
- 格式输出:用对齐格式打印边列表,符合需求样式
内容的提问来源于stack exchange,提问作者Elly
相关产品推荐
相关产品推荐

