【问题标题】:datetime x-axis matplotlib labels causing uncontrolled overlap日期时间 x 轴 matplotlib 标签导致不受控制的重叠
【发布时间】:2018-08-20 05:26:13
【问题描述】:

我正在尝试用'pandas.tseries.index.DatetimeIndex' 绘制熊猫series。 x 轴标签顽固地重叠,即使有几个建议的解决方案,我也无法使它们看起来像。

我试过stackoverflow solution suggesting to use autofmt_xdate,但没有用。

我也尝试了plt.tight_layout()的建议,但没有生效。

ax = test_df[(test_df.index.year ==2017) ]['error'].plot(kind="bar")
ax.figure.autofmt_xdate()
#plt.tight_layout()
print(type(test_df[(test_df.index.year ==2017) ]['error'].index))

更新:我使用条形图是个问题。常规时间序列图显示管理良好的标签。

【问题讨论】:

    标签: python pandas matplotlib


    【解决方案1】:

    pandas 条形图是一个分类图。它在刻度上的整数位置为每个索引显示一个条形图。因此,第一个条位于位置 0,下一个位于 1,依此类推。标签对应于数据帧的索引。如果您有 100 个条形图,您最终会得到 100 个标签。这是有道理的,因为 pandas 无法知道这些是否应该被视为类别或序数/数字数据。

    如果您使用普通的 matplotlib 条形图,它将以数字方式处理数据帧索引。这意味着条形图的位置根据实际日期而定,而标签则根据自动收录器放置。

    import pandas as pd
    import numpy as np; np.random.seed(42)
    import matplotlib.pyplot as plt
    
    datelist = pd.date_range(pd.datetime(2017, 1, 1).strftime('%Y-%m-%d'), periods=42).tolist()
    df = pd.DataFrame(np.cumsum(np.random.randn(42)), 
                      columns=['error'], index=pd.to_datetime(datelist))
    
    plt.bar(df.index, df["error"].values)
    plt.gcf().autofmt_xdate()
    plt.show()
    

    另外的优点是可以使用matplotlib.dates 定位器和格式化程序。例如。用自定义格式标记每个月的第一个和第十五个,

    import pandas as pd
    import numpy as np; np.random.seed(42)
    import matplotlib.pyplot as plt
    import matplotlib.dates as mdates
    
    datelist = pd.date_range(pd.datetime(2017, 1, 1).strftime('%Y-%m-%d'), periods=93).tolist()
    df = pd.DataFrame(np.cumsum(np.random.randn(93)), 
                      columns=['error'], index=pd.to_datetime(datelist))
    
    plt.bar(df.index, df["error"].values)
    plt.gca().xaxis.set_major_locator(mdates.DayLocator((1,15)))
    plt.gca().xaxis.set_major_formatter(mdates.DateFormatter("%d %b %Y"))
    plt.gcf().autofmt_xdate()
    plt.show()
    

    【讨论】:

      【解决方案2】:

      在您的情况下,最简单的方法是手动创建标签和间距,然后使用 ax.xaxis.set_major_formatter 应用它。

      这是一个可能的解决方案:

      由于没有提供样本数据,我试图在一个带有一些随机数的数据框中模拟您的数据集的结构。

      设置:

      # imports
      import pandas as pd
      import numpy as np
      import matplotlib.pyplot as plt
      import matplotlib.dates as mdates
      import matplotlib.ticker as ticker
      
      # A dataframe with random numbers ro run tests on
      np.random.seed(123456)
      rows = 100
      df = pd.DataFrame(np.random.randint(-10,10,size=(rows, 1)), columns=['error'])
      datelist = pd.date_range(pd.datetime(2017, 1, 1).strftime('%Y-%m-%d'), periods=rows).tolist()
      df['dates'] = datelist 
      df = df.set_index(['dates'])
      df.index = pd.to_datetime(df.index)
      
      test_df = df.copy(deep = True)
      
      # Plot of data that mimics the structure of your dataset
      ax = test_df[(test_df.index.year ==2017) ]['error'].plot(kind="bar")
      ax.figure.autofmt_xdate()
      plt.figure(figsize=(15,8))
      

      一种可能的解决方案:

      test_df = df.copy(deep = True)
      ax = test_df[(test_df.index.year ==2017) ]['error'].plot(kind="bar")
      plt.figure(figsize=(15,8))
      
      # Make a list of empty myLabels
      myLabels = ['']*len(test_df.index)
      
      # Set labels on every 20th element in myLabels
      myLabels[::20] = [item.strftime('%Y - %m') for item in test_df.index[::20]]
      ax.xaxis.set_major_formatter(ticker.FixedFormatter(myLabels))
      plt.gcf().autofmt_xdate()
      
      # Tilt the labels
      plt.setp(ax.get_xticklabels(), rotation=30, fontsize=10)
      plt.show()
      

      您可以通过检查strftime.org轻松更改标签格式

      【讨论】:

      • 这种做法的问题,从图中可以看出。您使用月份标签标记一个月内的一些任意日期,这会导致"2017-01" 在某个随机位置出现两次。
      • 同意。你的建议已经得到我的支持 =) 我喜欢我自己的建议的地方在于标签的密集度以及标签字符串的格式方面的灵活性。
      • 哦,也许我的回答并不清楚,但更改位置和格式的灵活性 正是使用数字轴的优势。我更新了它,这样就更清楚了。
      • 我不知道。非常好!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-14
      • 2019-06-28
      • 2015-05-02
      • 2012-11-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多