You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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.]

结果和预期不符,问题依然存在。


问题解决方法

你遇到的核心问题是坐标转换的时机错误,以及对变换矩阵的逻辑理解偏差:

  1. 变换矩阵依赖轴范围,必须先确定轴范围再转换
    Matplotlib的坐标变换矩阵是基于当前轴的范围生成的,如果你先执行转换再设置轴范围,变换会使用默认的轴范围(比如0-1),导致结果不符合预期。正确顺序是:先设置轴范围,再执行坐标转换。

  2. 纠正坐标转换逻辑

  • 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 07:25:20