Matplotlib坐标转换未达预期?技术问题求助
Matplotlib数据坐标与轴坐标转换问题
我正在尝试在Matplotlib中将数据坐标(data coordinates)转换为轴坐标(axes coordinates),以下是我的代码:
a, b = (.5,2) x = np.linspace(-1,4,100) y = [psi(xv,a,b) for xv in x] plt.figure(figsize=(10,5)) ax = plt.gca() point = (a,1) display = (369, 316.8) trans1 = ax.transData.transform([0,0]) print (trans1) trans = ax.transData.inverted().transform(trans1) print (trans) trans = ax.transAxes.inverted().transform(trans1) print (trans) plt.plot(trans[0], trans[1], 'ro') plt.plot(0,0, 'ro', transform=ax.transData) plt.plot(x,y, lw=3) plt.axhline(y = 1, color = 'r', linestyle = '--', lw=3, xmax=.3) plt.title('Psi Function', fontsize=30) plt.yticks([0, .2, .4, .6, .8, 1],['0','.2','','','','A'], fontsize = 'x-large') plt.xticks([-1, 0, 0.5, 2, 3, 4], ['','0', 'a', 'b', '', '']) plt.ylabel('$\Psi$', fontsize=25) plt.xlabel('$x$', fontsize=25) plt.grid()
我重点关注这段代码:
trans1 = ax.transData.transform([0,0]) print (trans1) trans = ax.transData.inverted().transform(trans1) print (trans) trans = ax.transAxes.inverted().transform(trans1) print (trans)
我的操作逻辑是:先把数据点(0,0)转换为屏幕坐标,然后尝试转换回数据坐标并打印结果,同时转换为轴坐标。我预期得到两个不同的结果——数据坐标下(0,0)是正确的,但因为轴并非从(0,0)开始,所以轴坐标的结果应该大于0。
我使用的是Matplotlib 3.5.1版本,不确定是否是版本导致的问题。
之后我修改代码,添加了坐标轴范围设置:
ax.set_xlim(0,2) ax.set_ylim(0,1.1) trans1 = ax.transData.transform([0,0]) print (trans1) trans = ax.transData.inverted().transform(trans1) print (trans) trans = ax.transAxes.inverted().transform(trans1)
得到的输出结果是:
[90. 45.] [ 0.00000000e+00 -2.77555756e-17] [0. 0.]
结果和预期不符,问题依然存在。
问题解决方法
你遇到的核心问题是坐标转换的时机错误,以及对变换矩阵的逻辑理解偏差:
变换矩阵依赖轴范围,必须先确定轴范围再转换
Matplotlib的坐标变换矩阵是基于当前轴的范围生成的,如果你先执行转换再设置轴范围,变换会使用默认的轴范围(比如0-1),导致结果不符合预期。正确顺序是:先设置轴范围,再执行坐标转换。纠正坐标转换逻辑
ax.transData:负责数据坐标→屏幕坐标的转换ax.transData.inverted():负责屏幕坐标→数据坐标的逆转换ax.transAxes:负责轴坐标→屏幕坐标的转换ax.transAxes.inverted():负责屏幕坐标→轴坐标的逆转换
要将数据坐标转为轴坐标,正确流程是:数据坐标→屏幕坐标→轴坐标。
以下是修正后的完整代码示例(补充了psi函数的示例定义):
import numpy as np import matplotlib.pyplot as plt def psi(x, a, b): # 示例psi函数定义,可根据实际需求替换 if x < a: return x/a elif a <= x <= b: return (b - x)/(b - a) else: return 0 a, b = (.5,2) x = np.linspace(-1,4,100) y = [psi(xv,a,b) for xv in x] plt.figure(figsize=(10,5)) ax = plt.gca() # 第一步:先设置轴范围 ax.set_xlim(-1, 4) ax.set_ylim(0, 1) # 第二步:执行坐标转换 # 数据坐标(0,0)转屏幕坐标 trans_screen = ax.transData.transform([0,0]) print("屏幕坐标:", trans_screen) # 屏幕坐标转回数据坐标 trans_data = ax.transData.inverted().transform(trans_screen) print("转回数据坐标:", trans_data) # 屏幕坐标转轴坐标 trans_axes = ax.transAxes.inverted().transform(trans_screen) print("轴坐标:", trans_axes) # 后续绘图代码 plt.plot(x,y, lw=3) plt.axhline(y = 1, color = 'r', linestyle = '--', lw=3, xmax=.3) plt.title('Psi Function', fontsize=30) plt.yticks([0, .2, .4, .6, .8, 1],['0','.2','','','','A'], fontsize = 'x-large') plt.xticks([-1, 0, 0.5, 2, 3, 4], ['','0', 'a', 'b', '', '']) plt.ylabel('$\Psi$', fontsize=25) plt.xlabel('$x$', fontsize=25) plt.grid() plt.show()
运行这段代码后,会得到数据点(0,0)的轴坐标为[0.2, 0.0],完全符合预期——x轴范围是-1到4,(0 - (-1))/(4 - (-1))=0.2,y轴从0开始,所以轴坐标y值为0。
内容的提问来源于stack exchange,提问作者Kiwiheretic
相关产品推荐
相关产品推荐

