matplotlib - 调用axes.cla()后,autofmt_xdate()无法旋转x轴标签

MrP*_*ayi 2 python matplotlib

我有两组数据需要根据时间绘制。我需要单独显示它们,并借助单选按钮(或类似的方式)一起显示它们。单选按钮代码基于/sf/answers/468828881/

在加载第一组数据之前,一切看起来都很好。每当要绘制下一组数据时,我都会清除轴并重新绘制数据。但是当我单击单选按钮中的下一项时,会显示新数据,但 x 轴不会旋转。有没有什么办法解决这一问题。

重现我面临的问题的示例代码

import datetime
import matplotlib.pyplot as plt
from matplotlib.widgets import RadioButtons
import matplotlib.dates as mdates

data0_usage = [45, 76, 20, 86, 79, 95, 14, 94, 59, 84]
data1_usage = [57, 79, 25, 28, 17, 46, 29, 52, 68, 92]
data0_timestamp = []


def draw_data_plot(ax, data_no):
    if data_no == 0:
        data_usage = data0_usage
        data_color = 'go'
    elif data_no == 1:
        data_usage = data1_usage
        data_color = 'ro'

    ax.plot_date(data0_timestamp, data_usage, data_color)
    ax.plot_date(data0_timestamp, data_usage, 'k', markersize=1)


def draw_plot():
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.grid(True)

    # Adjust the subplots region to leave some space for the sliders and buttons
    fig.subplots_adjust(left=0.25, bottom=0.25)

    # Beautify the dates on x axis
    time_format = mdates.DateFormatter('%Y-%b-%d %H:%M:%S')
    plt.gca().xaxis.set_major_formatter(time_format)
    plt.gcf().autofmt_xdate()

    # Draw data0 plot
    draw_data_plot(ax, 0)

    # Add a set of radio buttons for changing color
    color_radios_ax = fig.add_axes(
        [0.025, 0.5, 0.15, 0.15], axisbg='lightgoldenrodyellow')
    color_radios = RadioButtons(
        color_radios_ax, ('data 0', 'data 1', 'all'),
        active=0)

    def color_radios_on_clicked(label):
        ax.cla()
        ax.grid(True)
        if label == 'all':
            draw_data_plot(ax, 0)
            draw_data_plot(ax, 1)
        else:
            draw_data_plot(ax, int(label[5]))

        ax.xaxis.set_major_formatter(time_format)
        plt.gcf().autofmt_xdate()
        fig.canvas.draw_idle()

    color_radios.on_clicked(color_radios_on_clicked)
    plt.show()


current_date = datetime.datetime.today()
for days in range(0, 10):
    data0_timestamp.append(current_date + datetime.timedelta(days))
draw_plot()
Run Code Online (Sandbox Code Playgroud)

使用 Windows 10、Python 2.7.32、matplotlib 2.1.0

Imp*_*est 5

The problem

The reason plt.gcf().autofmt_xdate() fails for subsequent updates of the axes content is that at the point when it is called, there are axes inside the figure, which are no subplots. This is the axes created by fig.add_axes, being the radiobutton axes. autofmt_xdate will not know what to do with this axes, i.e. it would not know if this is the axes for which to rotate the labels or not, hence it will decide not to do anything. In the matplotlib source code this looks like

allsubplots = all(hasattr(ax, 'is_last_row') for ax in self.axes)
if len(self.axes) == 1:
    # rotate labels
else:
    if allsubplots:
        for ax in self.get_axes():
            if ax.is_last_row():
                #rotate labels
            else:
                #set labels invisible
Run Code Online (Sandbox Code Playgroud)

Because you have an axes, which is not a subplot, allsubplots == False and no rotation takes place.

The solution

The solution would be not to use autofmt_xdate(), but to do the work of rotating the ticklabels manually - which is really only 3 lines of code. Replace the line plt.gcf().autofmt_xdate() by

for label in ax.get_xticklabels():
    label.set_ha("right")
    label.set_rotation(30)
Run Code Online (Sandbox Code Playgroud)