Python Matplotlib-在保持正确的x值的同时跳过XTICK
我试图从两个熊猫数据帧中画出两个不同的东西,但是x轴给了一些问题。使用matplotlib.ticker跳过x记号时,不会跳过日期。结果是x轴值与绘制的不匹配 例如,当x记号设置为基数2时,您将看到日期增加了1 但当底部设置为4时,图形具有相同的间距,您可以在此处看到: 对于第二幅图像,目标是每滴答增加4天,因此应该是22、26、30等 以下是我正在使用的代码:Python Matplotlib-在保持正确的x值的同时跳过XTICK,python,pandas,matplotlib,Python,Pandas,Matplotlib,我试图从两个熊猫数据帧中画出两个不同的东西,但是x轴给了一些问题。使用matplotlib.ticker跳过x记号时,不会跳过日期。结果是x轴值与绘制的不匹配 例如,当x记号设置为基数2时,您将看到日期增加了1 但当底部设置为4时,图形具有相同的间距,您可以在此处看到: 对于第二幅图像,目标是每滴答增加4天,因此应该是22、26、30等 以下是我正在使用的代码: ax = plot2[['Date','change value']].plot(x='Date',color='red',alp
ax = plot2[['Date','change value']].plot(x='Date',color='red',alpha=1,linewidth=1.5)
plt.ylabel('Total Change')
plot_df[['Date','share change daily']].plot(x='Date',secondary_y=True,kind='bar',ax=ax,alpha=0.4,color='black',figsize=(6,2),label='Daily Change')
plt.ylabel('Daily Change')
ax.legend(['Total Change (L)','Daily Change'])
plt.xticks(plot_df.index,plot_df['Date'].values)
myLocator = mticker.MultipleLocator(base=4)
ax.xaxis.set_major_locator(myLocator)
感谢您的帮助!谢谢:)首先,我建议您将日期设置为数据帧的索引。这样,当您创建线图时,pandas可以自动很好地设置日期标签的格式,并且可以方便地使用该方法创建自定义格式 第二点与本例相关,因为在线图上绘制条形图会阻止您获取熊猫线图日期标签,因为x轴单位从0开始切换为整数单位(请注意,当您将日期用作字符串而不是对象(也称熊猫中的对象)时,情况也是如此)。您可以在创建线图(带有DatetimeIndex)后运行ax.Getxticks()并在创建条形图后再次运行来检查这一点 关于勾号定位器和格式化程序、默认设置以及定义自定义勾号和勾号标签的各种方式,有太多的特性,我不想在这里详细介绍。因此,我建议您参考文档以了解更多信息(尽管对于您的案例,您实际上并不需要这些信息):、以及包含及其参数的ticker模块 此外,您可以使用
ax.get_xaxis().get_major\u locator()
或ax.get_xaxis().get_major\u formatter()
(您可以对y轴和小刻度执行相同的操作)识别打印函数使用的默认刻度定位器和格式设置器,以了解引擎盖下发生的情况
继续解决你的问题。鉴于您希望为预定义的日期范围设置固定的勾号频率,我建议您避免显式选择勾号定位器和格式设置器,而只需创建所需的勾号列表和勾号标签。首先,这里有一些与您类似的示例数据:
import numpy as np # v 1.19.2
import pandas as pd # v 1.1.3
import matplotlib.pyplot as plt # v 3.3.2
rng = np.random.default_rng(seed=1) # random number generator
dti = pd.bdate_range(start='2020-07-22', end='2020-09-03')
daily = rng.normal(loc=0, scale=250, size=dti.size)
total = -1900 + np.cumsum(daily)
df = pd.DataFrame({'Daily Change': daily,
'Total Change': total},
index=dti)
df.head()
日期被设置为索引,这将简化创建绘图的代码(无需指定x
)。我使用与您给出的示例中相同的格式化参数,除了图形大小。请注意,对于设置记号和记号标签,我没有使用plt.xticks
,因为这是指包含条形图的次轴,并且由于某种原因,旋转
和ha
参数被忽略
label_daily, label_total = df.columns
# Create pandas line plot: note the 'use_index' parameter
ax = df.plot(y=label_total, color='red', alpha=1, linewidth=1.5,
use_index=False, ylabel=label_total)
# Create pandas bar plot: note that the second ylabel must be created
# after, else it overwrites the previous label on the left
df.plot(kind='bar', y=label_daily, color='black', alpha=0.4,
ax=ax, secondary_y=True, mark_right=False, figsize=(9, 4))
plt.ylabel(label_daily, labelpad=10)
# Place legend in a better location: note that because there are two
# Axes, the combined legend can only be edited with the fig.legend
# method, and the ax legend must be removed
ax.legend().remove()
plt.gcf().legend(loc=(0.11, 0.15))
# Create custom x ticks and tick labels
freq = 4 # business days
xticks = ax.get_xticks()
xticklabels = df.index[::freq].strftime('%b-%d')
ax.set_xticks(xticks[::freq])
ax.set_xticks(xticks, minor=True)
ax.set_xticklabels(xticklabels, rotation=0, ha='center')
plt.show()
可以找到格式化日期的代码
为了完整起见,这里有两种创建完全相同的记号的替代方法,但这次是通过显式使用matplotlib记号定位器和格式化程序 第一个备选方案与前面一样使用记号和记号标签列表,但这次将它们传递给和: 第二个备选方案利用选项在使用时在索引的每n个位置创建一个勾号,并将其与(而不是不推荐使用的
IndexFormatter
):
如您所见,这两个选项都比最初的示例更详细。您的
日期是列日期时间类型还是字符串类型?您应该尝试将参数传递给plt.xticks
两次,函数将第一个参数作为记号位置,第二个参数作为标签。您可能已经修改了刻度,但标签采用了旧值(即基础数据中的值),将其更改为datetime列没有任何区别,将其设置为索引也没有任何区别。我不知道你是什么意思,安德鲁。您只是想让其中两行以plt.xticks开头吗?如果是这样,那也没什么用。这个问题与这些、和有关。
label_daily, label_total = df.columns
# Create pandas line plot: note the 'use_index' parameter
ax = df.plot(y=label_total, color='red', alpha=1, linewidth=1.5,
use_index=False, ylabel=label_total)
# Create pandas bar plot: note that the second ylabel must be created
# after, else it overwrites the previous label on the left
df.plot(kind='bar', y=label_daily, color='black', alpha=0.4,
ax=ax, secondary_y=True, mark_right=False, figsize=(9, 4))
plt.ylabel(label_daily, labelpad=10)
# Place legend in a better location: note that because there are two
# Axes, the combined legend can only be edited with the fig.legend
# method, and the ax legend must be removed
ax.legend().remove()
plt.gcf().legend(loc=(0.11, 0.15))
# Create custom x ticks and tick labels
freq = 4 # business days
xticks = ax.get_xticks()
xticklabels = df.index[::freq].strftime('%b-%d')
ax.set_xticks(xticks[::freq])
ax.set_xticks(xticks, minor=True)
ax.set_xticklabels(xticklabels, rotation=0, ha='center')
plt.show()
import matplotlib.ticker as mticker
# Create custom x ticks and tick labels
freq = 4 # business days
maj_locator = mticker.FixedLocator(ax.get_xticks()[::freq])
min_locator = mticker.FixedLocator(ax.get_xticks())
ax.xaxis.set_major_locator(maj_locator)
ax.xaxis.set_minor_locator(min_locator)
maj_formatter = mticker.FixedFormatter(df.index[maj_locator.locs].strftime('%b-%d'))
ax.xaxis.set_major_formatter(maj_formatter)
plt.setp(ax.get_xticklabels(), rotation=0, ha='center')
import matplotlib.ticker as mticker
# Create custom x ticks and tick labels
maj_freq = 4 # business days
min_freq = 1 # business days
maj_locator = mticker.IndexLocator(maj_freq, 0)
min_locator = mticker.IndexLocator(min_freq, 0)
ax.xaxis.set_major_locator(maj_locator)
ax.xaxis.set_minor_locator(min_locator)
maj_formatter = mticker.FuncFormatter(lambda x, pos=None:
df.index[int(x)].strftime('%b-%d'))
ax.xaxis.set_major_formatter(maj_formatter)
plt.setp(ax.get_xticklabels(), rotation=0, ha='center')