如何在Matplotlib孪生轴的同x值对应点间绘制垂直线?
孪生轴(twinx)上同x值两点间绘制垂直线的实现方法
已知在同一坐标轴上可以实现两点间垂直线的绘制,但当两组点分别位于**孪生轴(twinx)**上时,由于两个轴的y轴刻度独立,直接绘制会出现坐标不匹配的问题。以下是给定的基础绘图代码:
import numpy as np import matplotlib.pyplot as plt import pandas as pd num_points = 100 # Generate x-values x_values = np.arange(num_points) # Create a decreasing linear function slope = -0.1 intercept = 5 y_values = slope * x_values + intercept # Add random noise noise_scale = 0.5 y_values += np.random.normal(0, noise_scale, num_points) # Create the numpy arrays random_points = np.column_stack((x_values, y_values)) random_numbers = np.random.uniform(-0.5, 0.5, num_points) # Creat DF df = pd.DataFrame(data={'x': x_values, 'y0': y_values, 'y1': random_numbers}) # Plot the points ax = df.plot.scatter(x='x', y='y0', c='b', marker='o', label='y0') ax.legend().set_visible(False) ax1 = ax.twinx() ax1.scatter(df['x'], df['y1'], color='darkorange', marker='o', label='y1') ax1.legend().set_visible(False) plt.show()
核心思路
孪生轴的y轴坐标空间是独立的,因此需要将其中一个轴的y坐标转换到另一个轴的坐标系统中,再进行直线绘制。具体步骤为:
- 将孪生轴(ax1)上的点坐标转换为屏幕显示坐标;
- 将屏幕显示坐标转换为主轴(ax)的坐标系统;
- 使用主轴绘制两点间的垂直线。
修改后的完整代码
import numpy as np import matplotlib.pyplot as plt import pandas as pd num_points = 100 # Generate x-values x_values = np.arange(num_points) # Create a decreasing linear function slope = -0.1 intercept = 5 y_values = slope * x_values + intercept # Add random noise noise_scale = 0.5 y_values += np.random.normal(0, noise_scale, num_points) # Create the numpy arrays random_points = np.column_stack((x_values, y_values)) random_numbers = np.random.uniform(-0.5, 0.5, num_points) # Creat DF df = pd.DataFrame(data={'x': x_values, 'y0': y_values, 'y1': random_numbers}) # Plot the points ax = df.plot.scatter(x='x', y='y0', c='b', marker='o', label='y0') ax.legend().set_visible(False) ax1 = ax.twinx() ax1.scatter(df['x'], df['y1'], color='darkorange', marker='o', label='y1') ax1.legend().set_visible(False) # 绘制同一x值下孪生轴两点间的垂直线 for x, y0, y1 in zip(df['x'], df['y0'], df['y1']): # 将ax1上的(x, y1)转换为屏幕坐标 screen_point = ax1.transData.transform((x, y1)) # 将屏幕坐标转换回ax的数据坐标 ax_y1 = ax.transData.inverted().transform(screen_point)[1] # 在ax上绘制垂直线 ax.plot([x, x], [y0, ax_y1], color='gray', linestyle='--', linewidth=0.8) plt.show()
代码说明
ax1.transData.transform((x, y1)):将ax1坐标系下的数据点转换为屏幕像素坐标;ax.transData.inverted().transform(screen_point):将屏幕坐标转换回ax坐标系下的数据坐标,提取y值即为ax中对应y1的位置;- 最后用
ax.plot绘制从y0到转换后y值的垂直线,可根据需求调整线条颜色、样式和宽度。
内容的提问来源于stack exchange,提问作者DrakeMurdoch
相关产品推荐
相关产品推荐

