
代码绘制成果展示












代码解释


第一部分

# =========================================================================================# ====================================== 1. 环境设置 =======================================# =========================================================================================import matplotlib.pyplot as pltimport matplotlib.patches as patchesimport pandas as pdimport numpy as npimport textwrapfrom collections import defaultdictplt.rcParams['font.family'] = 'Times New Roman'plt.rcParams['font.sans-serif'] = ['Times New Roman']plt.rcParams['axes.unicode_minus'] = False

第二部分

# =========================================================================================# ======================================2.颜色库=======================================# =========================================================================================COLOR_SCHEMES = {1: {'top': ['#d9dbe2', '#e9eaee', '#c4c8d3', '#a7acbd', '#8aa2ae', '#6a8f9d', '#567585', '#37505d'],'bottom': ['#b45d5a', '#cd6a69', '#df7375', '#e58385', '#eb9597', '#f0a7a8', '#f4b9ba', '#f8cbcb']},}

第三部分

# =========================================================================================# ======================================3.绘图函数=======================================# =========================================================================================def plot_advanced_forest_chart(df_real, scheme_id, line_width=3):top_labels = df_real['top_labels'] #顶部标签bottom_labels = df_real['bottom_labels'] #底部标签connections = df_real['connections'] #连接关系r_inner = 0.60 #内部半径r_wedge_in = 0.62 #扇形内径r_wedge_out = 0.85 #扇形外径r_ring_in = 0.87 #外环内径r_ring_out = 0.95 #外环外径gap = 1.5 #扇形间距

第四部分

top_start, top_end = 0.75, 179.25 #上半部分角度范围bottom_start, bottom_end = 180.75, 359.25 #下半部分角度范围bottom_wedge_angle = (bottom_end - bottom_start - gap * (len(bottom_labels) - 1)) / len(bottom_labels) #下半部分单个扇形角度bottom_angles = [] #下半部分角度列表curr = bottom_start #当前角度从起始开始#遍历下半部分标签for _ in range(len(bottom_labels)):bottom_angles.append((curr, curr + bottom_wedge_angle)) #记录起止角度curr += bottom_wedge_angle + gap #更新当前角度

第五部分

#扇形绘制函数def draw_sectors(labels, angles_list, colors):#遍历标签、角度、颜色for label, (th1, th2), color in zip(labels, angles_list, colors):th_center = (th1 + th2) / 2 #中心角th_rad = np.radians(th_center) #转弧度#添加扇区文本ax.text(x, #xy, #ylabel, #文本ha='center', #水平va='center', #垂直rotation=rot, #转fontsize=16, #字体大小color=get_text_color(color), #字体颜色fontweight='normal') #字体粗细

第六部分

#箭头绘制函数def draw_chord_arrow(th_src, th_tgt, color):rad_src, rad_tgt = np.radians(th_src), np.radians(th_tgt) #角度转弧度p0 = np.array([r_inner * np.cos(rad_src), r_inner * np.sin(rad_src)]) #起点curve = np.outer((1 - t) ** 2, p0) + np.outer(2 * (1 - t) * t, p1) + np.outer(t ** 2, p2) #贝塞尔曲线#箭头arrow_head = patches.Polygon([tip, p_left, p_right], #坐标closed=True, #闭合facecolor=color, #填充色edgecolor=color, #边色alpha=1, #透明度linewidth=0, #边宽zorder=3) #层ax.add_patch(arrow_head) #添加到图上

第七部分

#外圈弯曲文字绘制函数def draw_curved_text(text, r, center_angle, char_spacing=1.1, bottom=False):chars = list(text) #拆分文本total_arc = char_spacing * (len(chars) - 1) #总跨度角#上版部分if bottom:th_start = center_angle - total_arc / 2 #起角th_end = center_angle + total_arc / 2 #终角#下半部分else:va='center', #垂直rotation=rot, #旋转fontsize=18, #大小color='#222222', #颜色fontweight='bold') #加粗

第八部分

#绘制扇区draw_sectors(top_labels, top_angles, top_colors)draw_sectors(bottom_labels, bottom_angles, bottom_colors)#获取外环颜色top_ring_color = top_colors[len(top_colors) // 2]bottom_ring_color = bottom_colors[len(bottom_colors) // 2]#顶部外圈ax.add_patch(center=(0, 0), #坐标edgecolor='none')) #draw_curved_text("Characteristics of the airborne plastisphere", (r_ring_in + r_ring_out) / 2, 90) #顶部标题draw_curved_text("Planetary health threats", (r_ring_in + r_ring_out) / 2, 270, bottom=True) #底部标题

第九部分

out_counts, in_counts = defaultdict(int), defaultdict(int) #初始化发出连线的数量和接收连线的数量字典#遍历连接for src, tgt in connections:out_counts[src] += 1 #统计节点发出连线in_counts[tgt] += 1 #统计节点接收连线src_th = (th1_s + th2_s) / 2 #居中out_curr[src] += 1 #更新该节点连线次数th1_t, th2_t = bottom_angles[tgt] #提取目标扇形起止角span_t = th2_t - th1_t #目标扇形宽#多条线if in_counts[tgt] > 1:step = (span_t * 0.7) / (in_counts[tgt] - 1) #均分tgt_th = th1_t + span_t * 0.15 + in_curr[tgt] * step #汇入角

第十部分

# =========================================================================================# ======================================4.执行部分=======================================# =========================================================================================if __name__ == "__main__":excel_path = r'data.xlsx' #原始数据#读取数据df_nodes = pd.read_excel(excel_path, sheet_name='Nodes')df_edges = pd.read_excel(excel_path, sheet_name='Connections')raw_top_labels = df_nodes[df_nodes['NodeType'] == 'Top']['Label'].tolist() #顶部标签raw_bottom_labels = df_nodes[df_nodes['NodeType'] == 'Bottom']['Label'].tolist() #底部标签scheme_id = 1selected_hex_colors = COLOR_SCHEMES[scheme_id]print('正在绘制并保存方案:', scheme_id)plot_advanced_forest_chart(df_real, scheme_id)

如何应用到你自己的数据

1.设置原始数据的保存路径,执行部分:
excel_path = r'data.xlsx' #原始数据2.读取指定数据,执行部分:
df_nodes = pd.read_excel(excel_path, sheet_name='Nodes')df_edges = pd.read_excel(excel_path, sheet_name='Connections')raw_top_labels = df_nodes[df_nodes['NodeType'] == 'Top']['Label'].tolist() #顶部标签raw_bottom_labels = df_nodes[df_nodes['NodeType'] == 'Bottom']['Label'].tolist() #底部标签
3.设置是否要进行批量绘图,执行部分:
plot_all = True #是否批量绘图4.设置绘图结果的保存地址,绘图函数部分:
plt.savefig(fr'\scheme_{scheme_id}.pdf', bbox_inches='tight')
推荐


获取方式
