Pyplot如何减少xticks *和* xticklabels密度?

时间:2018-03-15 02:07:29

标签: python matplotlib plot

我必须绘制几条具有非常高的xtick密度的曲线,比如1000个日期字符串。为了防止这些刻度标签相互重叠,我手动将它们设置为相隔60个日期。代码如下:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

ts_index = pd.period_range(start="20060429", periods=1000).strftime("%Y%m%d")

fig = plt.figure(1)
ax = plt.subplot(1, 1, 1)
tick_spacing = 60

for i in range(5):
    plt.plot(ts_index, 1 + i * 0.01 * np.arange(0, 1000), label="group %d"%i)

plt.legend(loc='best')
plt.title(r'net value curves')

xticks = ax.get_xticks()
xlabels = ax.get_xticklabels()
ax.set_xticks(xticks[::tick_spacing])
ax.set_xticklabels(xlabels[::tick_spacing])


plt.xticks(rotation="vertical")
plt.xlabel(r'date')
plt.ylabel('net value')
plt.grid(True)
plt.show()

fig.savefig(r".\net_value_curves.png", )
fig.clf()

我正在使用Python 3.6内核在PyCharm Community Edition 2017.2.2中运行这段代码。现在有趣的是:每当我以正常的“运行”模式运行代码时(即只需点击执行按钮并让代码“自由”运行直到中断或终止),那么我得到的数字总是会错过xticklabels: enter image description here

但是,如果我以“调试”模式运行代码并逐步运行它,那么我会得到一个带有完整xticklabels的预期数字: enter image description here

这真的很奇怪。无论如何,我只希望找到一种方法可以确保我在正常的“运行”模式下获得所需的输出(第二个数字)。如何修改当前代码才能实现此目的?

提前致谢!

3 个答案:

答案 0 :(得分:1)

通常,Axis对象使用Locator对象计算并放置刻度。 LocatorFormatter应该可以轻松替换,Axis Locator。默认nbins=16似乎不适合您,因此您可以使用methods将其替换为您想要的任何内容。这个问题并不复杂,不足以编写自己的问题,因此我建议axes.xaxis.set_major_locator能够很好地满足您的需求。你的例子似乎适用于from matplotlib.ticker import MaxNLocator (这是你在图片中所拥有的,因为有17个滴答。

您需要添加导入:

xticks = ax.get_xticks()
xlabels = ax.get_xticklabels()
ax.set_xticks(xticks[::tick_spacing])
ax.set_xticklabels(xlabels[::tick_spacing])

您需要替换块

ax.xaxis.set_major_locator(MaxNLocator(nbins=16))

ax.xaxis.set_major_locator(MaxNLocator(16))

或只是

nbins

您可能想要使用其他参数(所有这些参数都必须是关键字,integer除外)。请特别注意Locator

请注意,对于FormatterAxis API,我们使用Axes对象,而不是AxesAxis是整个情节,而Axes就是刺上它的东西。 Axis通常包含两个{{1}}个对象以及您图中的所有其他内容。

答案 1 :(得分:1)

您的x轴数据是字符串。因此,每个数据点将获得一个滴答。这可能不是你想要的。而是使用日期绘制。因为您正在使用pandas,所以很容易转换,

dates = pd.to_datetime(ts_index, format="%Y%m%d")

然后您可以摆脱手动xtick定位和格式化,因为matplotlib会自动为您选择一些不错的刻度位置。

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

ts_index = pd.period_range(start="20060429", periods=1000).strftime("%Y%m%d")
dates = pd.to_datetime(ts_index, format="%Y%m%d")

fig, ax = plt.subplots()

for i in range(5):
    plt.plot(dates, 1 + i * 0.01 * np.arange(0, 1000), label="group %d"%i)

plt.legend(loc='best')
plt.title(r'net value curves')

plt.xticks(rotation="vertical")
plt.xlabel(r'date')
plt.ylabel('net value')
plt.grid(True)
plt.show()

enter image description here

但是,如果您希望对位置和格式进行一些手动控制,可以使用matplotlib.dates定位器和格式化程序。

# tick every 3 months
plt.gca().xaxis.set_major_locator(mdates.MonthLocator((1,4,7,10)))
# format as "%Y%m%d"
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter("%Y%m%d"))

enter image description here

答案 2 :(得分:0)

您可以将xticks标签的可见性设置为False

for label in plt.gca().xaxis.get_ticklabels()[::N]:
                label.set_visible(False)

这会将每个第N个标签设置为不可见。