我在matplotlib中设置usetext = True来使用Latex来管理我的绘图中的字体布局。现在,x轴和xticklabel之间的空间对于正值和负值是不同的,如图所示。
是否有可能获得相同的空间?
示例:
import numpy as np
import matplotlib.pyplot as plt
t = np.linspace(-10.0, 10.0, 100)
s = np.cos(t)
plt.rc('text', usetex=True)
plt.rc('font', family='serif', size=30)
plt.plot(t, s)
plt.show()
答案 0 :(得分:2)
不幸的是,这个bug已经存在了很长时间,而且这里的大多数答案都认为问题是关于水平对齐而不是垂直间距。
The bug是众所周知的,并且有一个补丁来修复它,但它尚未合并,并且在过去的一年半中被列为需要审核。
有趣的是,这是一个相当令人困惑的错误。最初出现的问题是,由于某些原因,TeX给出一个减号(和其他几个数学符号)的下降值,表明它延伸到了基线以下。 dvipng,用于在光栅后端创建标签,只是裁剪到可见,所以这没关系。但为了保持对齐实际上具有下行的东西,matplotlib有一个单独的系统dviread,它从dvi文件本身读取值。这会获得奇怪的下降值。然后matplotlib的对齐系统认为png的一部分假设低于基线,将其向下移动。
错误报告中的修复非常简单,但我不完全确定它是如何工作的。不过,我已经尝试过了,它确实有效。
当然,这个问题是在2013年被问到的,所以看起来这个补丁似乎不会很快被应用。那么有哪些替代方案?
一个简单的选择是在工作时忽略对齐问题,但是,在进行演示输出时,请使用pdf后端。如果您想要图像,可以随时使用其他软件进行转换。 pdf后端不会遇到同样的问题,因为它完全不同地处理TeX部分。
另一种选择是调整负xticks的位置。从理论上讲,你可以从_get_layout中拉出精确的调整,这将给你下降值,但我不知道如何转换值。所以这是一个只关注对齐的例子:
import numpy as np
import matplotlib.pyplot as plt
t = np.linspace(-10.0, 10.0, 100)
s = np.cos(t)
i = [-10,-5,0,5,10]
plt.rc('text', usetex=True)
plt.rc('font', family='serif', size=30)
plt.plot(t, s)
for n,l in zip(*plt.xticks()):
if n<0: l.set_position((0,0.014))
答案 1 :(得分:1)
这是一种“hacky”方式,我不确定为什么要修复它,但使用FormatStrFormatter
中的matplotlib.ticker
似乎可以修复它。唯一的区别是字体粗细看起来很粗。我似乎无法改变这一点,但也许你可以解决这个问题。
import numpy as np
import matplotlib.ticker as mtick
import matplotlib.pyplot as plt
t = np.linspace(-10.0, 10.0, 100)
s = np.cos(t)
plt.rc('text', usetex=True)
plt.rc('font', family='serif', size=30)
fig = plt.figure()
ax1 = fig.add_subplot(111)
ax1.plot(t, s)
fmtx = '%.0f%%'
fmty = '%.1f%%'
xticks = mtick.FormatStrFormatter(fmtx)
yticks = mtick.FormatStrFormatter(fmty)
ax1.xaxis.set_major_formatter(xticks)
ax1.yaxis.set_major_formatter(yticks)
plt.show()
答案 2 :(得分:0)
我修复这样的小问题的方法是将绘图保存为SVG,然后在我最喜欢的矢量图形程序(例如InkScape)中编辑它。这将允许您选择绘图的各个部分并移动它们,同时保留高质量的矢量图形。
答案 3 :(得分:-1)
所以(遗憾的是)我只能设法提出另一个&#34; hacky&#34;解决方案,但我想我会分享:
import numpy as np
import matplotlib as mplib
import matplotlib.pyplot as plt
import types
# set up few plot options
plt.rc('text', usetex=True)
plt.rc('font', family='serif', size=30)
# get some data to plot
t = np.linspace(-10.0, 10.0, 100)
s = np.cos(t)
# plot things
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(t, s)
# define and register onresize callback to handle new ticks that appear on resize
def onresize(event):
SHIFT = 0.5
for label in ax.get_xticklabels():
#print(label.get_text()) # test to see if new ticks appear as expected
label.set_ha('right')
label.customShiftValue = SHIFT
label.set_x = types.MethodType(
lambda self, x: mplib.text.Text.set_x(self, x+self.customShiftValue),
label)
cid = fig.canvas.mpl_connect('resize_event', onresize)
# hold plot open
plt.show(block=True)
产生以下输出
让我解释一下我在这里所做的事情。最初,我在for
- 循环中迭代了xticklabels并使用label.set_ha('right')
将所有xticklabels水平对齐到右边。然而,标签都是填充的,我没有缩小它们的边界框(甚至不确定它是否以这种方式工作!)。因此,我决定注册一个onresize回调函数,因为在调整大小时可能会出现新的xticklabels。然后,我扩充了set_x
函数(代码来自:https://stackoverflow.com/a/33688795/2402281,信用给他们)。不能手动调整SHIFT
变量可以做的唯一事情就是让画布大小进行一些有意义的计算,这些计算在[0.4,0.6]范围内,这似乎是良好的偏移值(经验测试.. )。
即使它只是另一个&#34; hacky&#34;解决方案提案,它可能有助于找到合适的答案!我希望它有所帮助。