R语言ggvoronoi绘制Voronoi图如何连接对应绿点与蓝点
问题修复方案
核心问题原因
绿点和对应蓝点无法正确连接,本质是偏移生成上下界点位时,没有保留原始数据行的配对映射关系:两套点位独立生成后如果经过排序、去重、索引重置等操作,数组顺序会错位,直接连线会匹配到错误的点。另外最开始遇到的点位出界问题,是因为直接用原始upper/lower绝对值做坐标映射,没有做相对偏移,导致数值极值点超出绘图边界。
可直接复用的实现步骤
- 偏移计算阶段绑定配对关系
不要把lower、upper偏移后的点位拆成独立数据集,直接在原始数据框中新增列存储两类点位的坐标,每一行的坐标天然对应同一组配对点,从根源避免错位。偏移量用相对比例控制,不要直接缩放原始字段值,保留数值的相对差异。import pandas as pd import matplotlib.pyplot as plt from scipy.spatial import Voronoi, voronoi_plot_2d # 偏移系数可根据显示效果调整,数值越小点位越聚拢 OFFSET_RATIO = 0.07 # 原始df包含x/y/fit/lower/upper五个字段 df = pd.read_csv("你的样例数据路径") # 逐行计算偏移后的坐标,保留配对关系 df['x_low'] = df['x'] + (df['lower'] - df['fit']) * OFFSET_RATIO df['y_low'] = df['y'] + (df['lower'] - df['fit']) * OFFSET_RATIO df['x_up'] = df['x'] + (df['upper'] - df['fit']) * OFFSET_RATIO df['y_up'] = df['y'] + (df['upper'] - df['fit']) * OFFSET_RATIO - 按固定顺序绘图,避免打乱点位顺序
绘图顺序严格遵循「底图→双Voronoi图层→配对连线→散点标注」,连线时逐行读取同一条记录的两对坐标,不要对点位数组做排序类操作。同时自动适配坐标轴范围,解决点位出界问题。# 生成两套Voronoi网格 vor_low = Voronoi(df[['x_low', 'y_low']].values) vor_up = Voronoi(df[['x_up', 'y_up']].values) fig, ax = plt.subplots(figsize=(10, 10), dpi=100) # 叠加两层不同配色的Voronoi填充 voronoi_plot_2d(vor_low, ax=ax, show_vertices=False, line_width=0, point_size=0, face_colors='#a6cfff', alpha=0.6) voronoi_plot_2d(vor_up, ax=ax, show_vertices=False, line_width=0, point_size=0, face_colors='#ffb3b3', alpha=0.6) # 逐行绘制配对连线,不会出现错位 for _, row in df.iterrows(): # 蓝点(上下偏移点)和绿点(fit原始点)的连线 ax.plot([row['x_low'], row['x']], [row['y_low'], row['y']], color='#666666', linewidth=0.7, zorder=2) ax.plot([row['x_up'], row['x']], [row['y_up'], row['y']], color='#666666', linewidth=0.7, zorder=2) # 绘制散点 ax.scatter(df['x_low'], df['y_low'], color='#165dff', s=12, zorder=3, label='lower/upper偏移点位') ax.scatter(df['x_up'], df['y_up'], color='#165dff', s=12, zorder=3) ax.scatter(df['x'], df['y'], color='#00b42a', s=18, zorder=4, label='fit值点位') # 自动适配坐标轴范围,避免点位出界 x_min = df[['x_low', 'x_up', 'x']].min().min() * 0.95 x_max = df[['x_low', 'x_up', 'x']].max().max() * 1.05 y_min = df[['y_low', 'y_up', 'y']].min().min() * 0.95 y_max = df[['y_low', 'y_up', 'y']].max().max() * 1.05 ax.set_xlim(x_min, x_max) ax.set_ylim(y_min, y_max) ax.legend() plt.show()
避坑提示
不要在坐标数组生成后单独做排序、筛选,生成Voronoi网格和点位前,如果需要过滤异常值、去重,必须先在原始DataFrame上完成操作,再计算偏移坐标,否则会破坏行级配对关系,导致连线错位。如果点位聚拢效果不符合预期,直接调整
OFFSET_RATIO参数即可,不需要改动核心逻辑。
内容的提问来源于stack exchange,提问作者Dollar Tune-bill
相关产品推荐
相关产品推荐

