matplotlib - 如何在matplotlib中更改底部x轴顶部的一些x轴刻度标签的位置?
问题描述
这是我当前的脚本:
#!/usr/bin/env python3
import math
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
"""
Setup for a typical explanatory-style illustration style graph.
"""
h = 2
x = np.linspace(-np.pi, np.pi, 100)
y = 2 * np.sin(x)
rc = {
# Tick in the middle of the axis line.
'xtick.direction' : 'inout',
'ytick.direction' : 'inout',
# Bold is easier to read when we have few ticks.
'font.weight': 'bold',
'xtick.labelbottom': False,
'xtick.labeltop': True,
}
with plt.rc_context(rc):
fig, ax = plt.subplots()
ax.plot(x, y)
ax.set_title(
'2 sin(x), not $\\sqrt{2\\pi}$',
# TODO make LaTeX part bold?
# https://stackoverflow.com/questions/14324477/bold-font-weight-for-latex-axes-label-in-matplotlib
fontweight='bold',
# Too close otherwise.
# https://stackoverflow.com/questions/16419670/increase-distance-between-title-and-plot-in-matplolib/56738085
pad=20
)
# Custom visible plot area.
# ax.set_xlim(-3, 3)
ax.set_ylim(-2.5, 2.5)
# Axes
# Axes on center:
# https://stackoverflow.com/questions/31556446/how-to-draw-axis-in-the-middle-of-the-figure
ax.spines['left'].set_position('zero')
ax.spines['right'].set_visible(False)
ax.spines['bottom'].set_position('zero')
ax.spines['top'].set_visible(False)
# Axes with arrow:
# https://stackoverflow.com/questions/33737736/matplotlib-axis-arrow-tip
ax.plot(1, 0, ls="", marker=">", ms=10, color="k",
transform=ax.get_yaxis_transform(), clip_on=False)
ax.plot(0, 1, ls="", marker="^", ms=10, color="k",
transform=ax.get_xaxis_transform(), clip_on=False)
# Ticks
ax.xaxis.set_ticks_position('bottom')
ax.yaxis.set_ticks_position('left')
# Make ticks a bit longer.
ax.tick_params(width=1, length=10)
# Select tick positions
# https://stackoverflow.com/questions/12608788/changing-the-tick-frequency-on-x-or-y-axis-in-matplotlib
xticks = np.arange(math.ceil(min(x)), math.floor(max(x)) + 1, 1)
yticks = np.arange(math.ceil(min(y)) - 1, math.floor(max(y)) + 2, 1)
# Remove 0.
xticks = np.setdiff1d(xticks, [0])
yticks = np.setdiff1d(yticks, [0])
ax.xaxis.set_ticks(xticks)
ax.yaxis.set_ticks(yticks)
# Another approach. But because I want to be able to remove the 0,
# anyways, I just explicitly give all ticks instead.
# ax.xaxis.set_major_locator(matplotlib.ticker.MultipleLocator(1.0))
# ax.yaxis.set_major_locator(matplotlib.ticker.MultipleLocator(1.0))
# Annotations.
ax.plot([0, np.pi/2], [h, h], '--r')
ax.plot([np.pi/2, np.pi/2], [h, 0], '--r')
ax.plot(np.pi/2, h, marker='o', linewidth=2, markersize=10,
markerfacecolor='w', markeredgewidth=1.5, markeredgecolor='black')
plt.savefig(
'main.png',
format='png',
bbox_inches='tight'
)
plt.clf()
这是输出:
这就是我想要的(用 GIMP 破解),注意现在负刻度标签是如何在轴的另一侧的。
我尝试添加:
for tick in ax.xaxis.get_majorticklabels():
tick.set_verticalalignment("bottom")
如答案所示:如何在 matplotlib 中移动刻度标签?但这并没有将刻度标签向上移动得足够多,而是使标签显示在轴的顶部。
在 matplotlib 3.2.2 上测试。
解决方案
以下代码将调整刻度的垂直对齐方式,具体取决于它们是在负 x 值还是正 x 值。然而,这还不够,因为标签实际上锚定在刻度线的底部。因此,我稍微调整了它们的 y 位置,但是您必须使用该值才能获得所需的输出
# adjust the xticks so that they are on top when x<0 and on the bottom when x≥0
ax.spines['top'].set_visible(True)
ax.spines['top'].set_position('zero')
ax.spines['bottom'].set_visible(True)
ax.spines['bottom'].set_position('zero')
ax.xaxis.set_tick_params(which='both', top=True, labeltop=True,
bottom=True, labelbottom=True)
fig.canvas.draw()
for tick in ax.xaxis.get_major_ticks():
print(tick.get_loc())
if tick.get_loc()<0:
tick.tick1line.set_visible(False)
tick.label1.set_visible(False)
else:
tick.tick2line.set_visible(False)
tick.label2.set_visible(False)
完整代码:
import math
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
"""
Setup for a typical explanatory-style illustration style graph.
"""
h = 10
x = np.linspace(-np.pi, np.pi, 100)
y = h * np.sin(x)
rc = {
# Tick in the middle of the axis line.
'xtick.direction' : 'inout',
'ytick.direction' : 'inout',
# Bold is easier to read when we have few ticks.
'font.weight': 'bold',
'xtick.labelbottom': False,
'xtick.labeltop': True,
}
with plt.rc_context(rc):
fig, ax = plt.subplots()
ax.plot(x, y)
ax.set_title(
'2 sin(x), not $\\sqrt{2\\pi}$',
# TODO make LaTeX part bold?
# https://stackoverflow.com/questions/14324477/bold-font-weight-for-latex-axes-label-in-matplotlib
fontweight='bold',
# Too close otherwise.
# https://stackoverflow.com/questions/16419670/increase-distance-between-title-and-plot-in-matplolib/56738085
pad=20
)
# Custom visible plot area.
# ax.set_xlim(-3, 3)
ax.set_ylim(-2.5, 2.5)
# Axes
# Axes on center:
# https://stackoverflow.com/questions/31556446/how-to-draw-axis-in-the-middle-of-the-figure
ax.spines['left'].set_position('zero')
ax.spines['right'].set_visible(False)
ax.spines['bottom'].set_position('zero')
ax.spines['top'].set_visible(False)
# Axes with arrow:
# https://stackoverflow.com/questions/33737736/matplotlib-axis-arrow-tip
ax.plot(1, 0, ls="", marker=">", ms=10, color="k",
transform=ax.get_yaxis_transform(), clip_on=False)
ax.plot(0, 1, ls="", marker="^", ms=10, color="k",
transform=ax.get_xaxis_transform(), clip_on=False)
# Ticks
ax.xaxis.set_ticks_position('bottom')
ax.yaxis.set_ticks_position('left')
# Make ticks a bit longer.
ax.tick_params(width=1, length=10)
# Select tick positions
# https://stackoverflow.com/questions/12608788/changing-the-tick-frequency-on-x-or-y-axis-in-matplotlib
xticks = np.arange(math.ceil(min(x)), math.floor(max(x)) + 1, 1)
yticks = np.arange(math.ceil(min(y)) - 1, math.floor(max(y)) + 2, 1)
# Remove 0.
xticks = np.setdiff1d(xticks, [0])
yticks = np.setdiff1d(yticks, [0])
ax.xaxis.set_ticks(xticks)
ax.yaxis.set_ticks(yticks)
# Another approach. But because I want to be able to remove the 0,
# anyways, I just explicitly give all ticks instead.
# ax.xaxis.set_major_locator(matplotlib.ticker.MultipleLocator(1.0))
# ax.yaxis.set_major_locator(matplotlib.ticker.MultipleLocator(1.0))
for g,t in zip(ax.get_xticks(),ax.get_xticklabels()):
if g<0:
t.set_va('bottom')
else:
t.set_va('top')
t.set_transform(ax.transData)
t.set_position((g,0.15*-(g/abs(g))))
# Annotations.
ax.plot([0, np.pi/2], [h, h], '--r')
ax.plot([np.pi/2, np.pi/2], [h, 0], '--r')
ax.plot(np.pi/2, h, marker='o', linewidth=2, markersize=10,
markerfacecolor='w', markeredgewidth=1.5, markeredgecolor='black')
# adjust the xticks so that they are on top when x<0 and on the bottom when x≥0
ax.spines['top'].set_visible(True)
ax.spines['top'].set_position('zero')
ax.spines['bottom'].set_visible(True)
ax.spines['bottom'].set_position('zero')
ax.xaxis.set_tick_params(which='both', top=True, labeltop=True,
bottom=True, labelbottom=True)
fig.canvas.draw()
for tick in ax.xaxis.get_major_ticks():
print(tick.get_loc())
if tick.get_loc()<0:
tick.tick1line.set_visible(False)
tick.label1.set_visible(False)
else:
tick.tick2line.set_visible(False)
tick.label2.set_visible(False)
推荐阅读
- css - 图像悬停时的css下拉菜单
- swift - Swift:绘图开始时图像丢失纵横比
- c# - Azure Active Directory B2C 未反序列化 MVC 项目中的 httpContext.Session
- amazon-web-services - AWS Lambda 内部的 Parameter Store 请求超时
- google-cloud-pubsub - Pubsub 以稳定的速度拉动?
- html - 如何对齐段落?
- php - 我的php编码有什么问题?[将图像从 html 表单保存到数据库]
- python - 如何限制稀疏梯度每个维度的绝对值过大?
- python - 使用 Python 从 PDF 多页列中提取字符串数据
- c# - 未找到 C# 递归依赖项