使用python创建、管理、分析和可视化“欲望”之间的关系网络图
图结构构建:
- 使用
networkx
库创建一个有向图 (DiGraph
)。 - 可以添加代表不同“欲望”(如“成功”、“幸福”、“健康”)的节点 (Nodes),并为每个节点设置属性,如欲望强度 (
intensity
)、描述 (description
)、类别 (category
) 和颜色 (color
)。 - 可以添加表示欲望之间关系(如“促进”、“影响”)的有向边 (Edges),并设置关系强度 (
strength
)、类型 (relation_type
) 和描述。
- 使用
图属性管理:
- 提供方法来移除节点、更新节点和边的属性。
- 允许设置图的可视化布局(如 spring, circular, kamada_kawai 等)和节点颜色映射。
图分析:
- 中心性分析: 计算图中每个节点的多种中心性指标(度中心性、接近中心性、中介中心性、PageRank),用以衡量节点在网络中的重要性或影响力。
- 文本相似度分析: 基于节点的描述文本,使用 TF-IDF 向量和余弦相似度计算节点之间的语义相似度,并将这种相似性作为新的关系边添加到图中。
- 社区检测: 使用 Louvain 算法检测图中节点形成的社区(紧密连接的子群)。
图可视化:
- 使用
matplotlib
提供强大的图形可视化功能。 - 节点的大小可以反映欲望强度,颜色可以基于社区归属或强度自定义。
- 边的宽度可以反映关系强度,颜色可以区分不同类型的关系(如普通关系和语义相似关系)。
- 支持显示节点标签、边标签、图例和标题,并特别处理了中文字体显示问题。
- 使用
- 代码
import networkx as nx
import matplotlib.pyplot as plt
import matplotlib as mpl
import numpy as np
import json
from collections import defaultdict
import warnings
import os
import platform# 解决中文显示问题
def set_chinese_font():"""设置中文字体支持"""system = platform.system()if system == 'Windows':plt.rcParams['font.sans-serif'] = ['Microsoft YaHei', 'SimHei']elif system == 'Darwin':plt.rcParams['font.sans-serif'] = ['PingFang HK', 'Heiti SC']else:plt.rcParams['font.sans-serif'] = ['WenQuanYi Micro Hei', 'WenQuanYi Zen Hei']plt.rcParams['axes.unicode_minus'] = False# 设置中文字体
set_chinese_font()warnings.filterwarnings("ignore", category=UserWarning)class LacanianDesireGraph:def __init__(self):"""初始化拉康式欲望图解"""self.graph = nx.DiGraph()self.node_attributes = {}self.edge_attributes = {}self.layout = "kamada_kawai"# 拉康理论中的关键元素self.symbolic_chain = [] # 象征链(能指链)self.imaginary_vector = [] # 想象矢量self.other = None # 大他者 (A)self.point_de_capiton = None # 缝合点 s(A)self.mythical_subject = None # 前语言主体 (△)self.split_subject = None # 割裂主体 (Ꞩ)# 双重结构self.conscious_chain = [] # 有意识能指链(所述层面)self.unconscious_chain = [] # 无意识能指链(能述层面)# 颜色映射self.color_map = {"symbolic": "blue","imaginary": "red","other": "purple","subject": "green","point_de_capiton": "gold","conscious": "cyan","unconscious": "magenta"}def add_symbolic_element(self, signifier, position=None):"""添加象征元素(能指)"""self.graph.add_node(signifier)self.node_attributes[signifier] = {'type': 'symbolic','position': position,'chain': 'symbolic','shape': 'o' # 圆形}self.symbolic_chain.append(signifier)# 自动连接象征链if len(self.symbolic_chain) > 1:prev = self.symbolic_chain[-2]self.add_relation(prev, signifier, relation_type="symbolic_chain")def add_imaginary_vector(self, vector_name, source, target):"""添加想象矢量"""self.graph.add_node(vector_name)self.node_attributes[vector_name] = {'type': 'imaginary_vector','shape': 'd' # 菱形 (使用字符代码'd'而不是字符串'diamond')}self.imaginary_vector.append(vector_name)# 连接源和目标self.add_relation(source, vector_name, relation_type="imaginary_source")self.add_relation(vector_name, target, relation_type="imaginary_target")def set_other(self, other_name):"""设置大他者 (A)"""if other_name not in self.graph.nodes:self.add_symbolic_element(other_name)self.other = other_nameself.node_attributes[other_name]['type'] = 'other'def set_point_de_capiton(self, point_name):"""设置缝合点 s(A)"""if point_name not in self.graph.nodes:self.add_symbolic_element(point_name)self.point_de_capiton = point_nameself.node_attributes[point_name]['type'] = 'point_de_capiton'def set_mythical_subject(self, subject_name):"""设置前语言主体 (△)"""self.graph.add_node(subject_name)self.node_attributes[subject_name] = {'type': 'mythical_subject','shape': '^' # 三角形 (使用字符代码'^'而不是字符串'triangle')}self.mythical_subject = subject_namedef set_split_subject(self, subject_name):"""设置割裂主体 (Ꞩ)"""self.graph.add_node(subject_name)self.node_attributes[subject_name] = {'type': 'split_subject','shape': 's' # 正方形 (使用字符代码's'而不是字符串'square')}self.split_subject = subject_namedef add_conscious_element(self, signifier):"""添加有意识能指(所述层面)"""self.graph.add_node(signifier)self.node_attributes[signifier] = {'type': 'conscious','chain': 'conscious','shape': 'o' # 圆形}self.conscious_chain.append(signifier)# 自动连接意识链if len(self.conscious_chain) > 1:prev = self.conscious_chain[-2]self.add_relation(prev, signifier, relation_type="conscious_chain")def add_unconscious_element(self, signifier):"""添加无意识能指(能述层面)"""self.graph.add_node(signifier)self.node_attributes[signifier] = {'type': 'unconscious','chain': 'unconscious','shape': 'o' # 圆形}self.unconscious_chain.append(signifier)# 自动连接无意识链if len(self.unconscious_chain) > 1:prev = self.unconscious_chain[-2]self.add_relation(prev, signifier, relation_type="unconscious_chain")def add_relation(self, source, target, strength=1.0, relation_type="general"):"""添加节点间关系"""if source not in self.graph.nodes or target not in self.graph.nodes:raise ValueError("源节点或目标节点不存在")self.graph.add_edge(source, target)self.edge_attributes[(source, target)] = {'weight': strength,'type': relation_type}def visualize(self, figsize=(14, 12)):"""可视化拉康欲望图解"""plt.figure(figsize=figsize)# 计算布局if self.layout == "spring":pos = nx.spring_layout(self.graph, seed=42)elif self.layout == "circular":pos = nx.circular_layout(self.graph)elif self.layout == "kamada_kawai":pos = nx.kamada_kawai_layout(self.graph)elif self.layout == "spectral":pos = nx.spectral_layout(self.graph)else:pos = nx.random_layout(self.graph)# 准备节点属性node_colors = []node_shapes = []for node in self.graph.nodes:node_type = self.node_attributes[node].get('type', 'symbolic')shape = self.node_attributes[node].get('shape', 'o') # 默认圆形node_shapes.append(shape)if node_type == 'other':node_colors.append(self.color_map['other'])elif node_type == 'point_de_capiton':node_colors.append(self.color_map['point_de_capiton'])elif node_type == 'mythical_subject':node_colors.append(self.color_map['subject'])elif node_type == 'split_subject':node_colors.append(self.color_map['subject'])elif node_type == 'imaginary_vector':node_colors.append(self.color_map['imaginary'])elif node_type == 'conscious':node_colors.append(self.color_map['conscious'])elif node_type == 'unconscious':node_colors.append(self.color_map['unconscious'])else:node_colors.append(self.color_map['symbolic'])# 准备边属性edge_colors = []edge_styles = []for edge in self.graph.edges:edge_type = self.edge_attributes[edge]['type']if edge_type == "symbolic_chain":edge_colors.append(self.color_map['symbolic'])edge_styles.append('solid')elif edge_type == "imaginary_source" or edge_type == "imaginary_target":edge_colors.append(self.color_map['imaginary'])edge_styles.append('dashed')elif edge_type == "conscious_chain":edge_colors.append(self.color_map['conscious'])edge_styles.append('solid')elif edge_type == "unconscious_chain":edge_colors.append(self.color_map['unconscious'])edge_styles.append('dotted')else:edge_colors.append('gray')edge_styles.append('solid')# 绘制节点 - 需要按形状分组绘制shape_groups = defaultdict(list)for i, node in enumerate(self.graph.nodes):shape_groups[node_shapes[i]].append(node)for shape, nodes in shape_groups.items():nx.draw_networkx_nodes(self.graph, pos,nodelist=nodes,node_shape=shape,node_size=1500,node_color=[node_colors[list(self.graph.nodes).index(n)] for n in nodes],alpha=0.8)# 绘制边 - 需要按样式分组绘制style_groups = defaultdict(list)for i, edge in enumerate(self.graph.edges):style_groups[edge_styles[i]].append(edge)for style, edges in style_groups.items():nx.draw_networkx_edges(self.graph, pos,edgelist=edges,edge_color=[edge_colors[list(self.graph.edges).index(e)] for e in edges],style=style,arrows=True,arrowstyle='->',arrowsize=20,alpha=0.7)# 绘制标签labels = {n: n for n in self.graph.nodes}nx.draw_networkx_labels(self.graph, pos,labels=labels,font_size=10,font_family=plt.rcParams['font.sans-serif'][0])# 添加图例from matplotlib.lines import Line2Dlegend_elements = [Line2D([0], [0], marker='o', color='w', label='象征元素 (能指)',markerfacecolor=self.color_map['symbolic'], markersize=10),Line2D([0], [0], marker='d', color='w', label='想象矢量',markerfacecolor=self.color_map['imaginary'], markersize=10),Line2D([0], [0], marker='o', color='w', label='大他者 (A)',markerfacecolor=self.color_map['other'], markersize=10),Line2D([0], [0], marker='o', color='w', label='缝合点 s(A)',markerfacecolor=self.color_map['point_de_capiton'], markersize=10),Line2D([0], [0], marker='^', color='w', label='前语言主体 (△)',markerfacecolor=self.color_map['subject'], markersize=10),Line2D([0], [0], marker='s', color='w', label='割裂主体 (Ꞩ)',markerfacecolor=self.color_map['subject'], markersize=10),Line2D([0], [0], marker='o', color='w', label='有意识能指',markerfacecolor=self.color_map['conscious'], markersize=10),Line2D([0], [0], marker='o', color='w', label='无意识能指',markerfacecolor=self.color_map['unconscious'], markersize=10),Line2D([0], [0], color=self.color_map['symbolic'], lw=2, label='象征链'),Line2D([0], [0], color=self.color_map['imaginary'], lw=2, linestyle='dashed', label='想象矢量'),Line2D([0], [0], color=self.color_map['conscious'], lw=2, label='有意识链'),Line2D([0], [0], color=self.color_map['unconscious'], lw=2, linestyle='dotted', label='无意识链'),]plt.legend(handles=legend_elements,loc='best',prop={'family': plt.rcParams['font.sans-serif'][0]})plt.title("拉康欲望图解", fontproperties={'family': plt.rcParams['font.sans-serif'][0]})plt.axis('off')plt.tight_layout()plt.show()def to_dict(self):"""将图转换为字典格式"""return {"symbolic_chain": self.symbolic_chain,"imaginary_vector": self.imaginary_vector,"other": self.other,"point_de_capiton": self.point_de_capiton,"mythical_subject": self.mythical_subject,"split_subject": self.split_subject,"conscious_chain": self.conscious_chain,"unconscious_chain": self.unconscious_chain,"nodes": [{"name": node,"attributes": self.node_attributes[node]} for node in self.graph.nodes],"edges": [{"source": edge[0],"target": edge[1],"attributes": self.edge_attributes[edge]} for edge in self.graph.edges]}def save_to_json(self, filename):"""将图保存为JSON文件"""graph_dict = self.to_dict()with open(filename, 'w', encoding='utf-8') as f:json.dump(graph_dict, f, indent=2, ensure_ascii=False)@classmethoddef load_from_json(cls, filename):"""从JSON文件加载图"""with open(filename, 'r', encoding='utf-8') as f:graph_dict = json.load(f)dg = cls()# 重建基本结构dg.symbolic_chain = graph_dict.get("symbolic_chain", [])dg.imaginary_vector = graph_dict.get("imaginary_vector", [])dg.other = graph_dict.get("other")dg.point_de_capiton = graph_dict.get("point_de_capiton")dg.mythical_subject = graph_dict.get("mythical_subject")dg.split_subject = graph_dict.get("split_subject")dg.conscious_chain = graph_dict.get("conscious_chain", [])dg.unconscious_chain = graph_dict.get("unconscious_chain", [])# 添加节点for node_data in graph_dict["nodes"]:name = node_data["name"]attributes = node_data["attributes"]dg.graph.add_node(name)dg.node_attributes[name] = attributes# 添加边for edge_data in graph_dict["edges"]:source = edge_data["source"]target = edge_data["target"]attributes = edge_data["attributes"]dg.graph.add_edge(source, target)dg.edge_attributes[(source, target)] = attributesreturn dg# 示例用法:构建拉康欲望图解的基本单位
def create_elementary_cell():"""创建欲望图解的基本单位"""dg = LacanianDesireGraph()# 添加象征链元素dg.add_symbolic_element("S1")dg.add_symbolic_element("S2")# 设置大他者 (A) 和缝合点 s(A)dg.set_other("A")dg.set_point_de_capiton("s(A)")# 添加想象矢量dg.add_imaginary_vector("V", "S1", "S2")# 设置主体dg.set_mythical_subject("△")dg.set_split_subject("Ꞩ")# 添加关系dg.add_relation("A", "s(A)", relation_type="other_to_point")dg.add_relation("s(A)", "S1", relation_type="point_to_signifier")dg.add_relation("△", "Ꞩ", relation_type="subject_transformation")return dg# 示例用法:构建完整欲望图解
def create_full_desire_graph():"""创建完整的欲望图解"""dg = create_elementary_cell()# 添加有意识能指链(所述层面)dg.add_conscious_element("C1")dg.add_conscious_element("C2")# 添加无意识能指链(能述层面)dg.add_unconscious_element("U1")dg.add_unconscious_element("U2")# 连接双重结构dg.add_relation("s(A)", "C1", relation_type="conscious_link")dg.add_relation("s(A)", "U1", relation_type="unconscious_link")dg.add_relation("C2", "U2", relation_type="duality_link")return dgif __name__ == "__main__":# 创建基本单位elementary = create_elementary_cell()elementary.visualize()elementary.save_to_json("lacanian_elementary_cell.json")# 创建完整图解full_graph = create_full_desire_graph()full_graph.visualize()full_graph.save_to_json("lacanian_full_graph.json")# 加载示例# loaded_graph = LacanianDesireGraph.load_from_json("lacanian_full_graph.json")# loaded_graph.visualize()