【问题标题】:Center x-axis labels in line plot折线图中的中心 x 轴标签
【发布时间】:2018-08-27 18:05:13
【问题描述】:

我正在构建一个包含两条线的线图,一条用于高温,另一条用于低温。 x 轴基于日期时间格式(2014-01-01 等)的一整年的天数。但是,我更改了几个月(一月、二月、三月等)的标签——而不是数据。问题是第一个标签“Jan”在原点。我想要的是将所有标签向右移动以使它们在刻度之间居中

fig, ax = plt.subplots()

plt.plot(x, y1)
plt.plot(x, y2)

# Change x-axis from %y-%m-%d format to %m:
monthsFmt = mdates.DateFormatter('%m')
plt.gca().xaxis.set_major_formatter(monthsFmt)

# Replace numeric x-axis labels (1,2,3, ..., 12) for abbreviations of months ('Jan', 'Feb', 'Mar', etc.):
labels = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
ax.set_xticklabels(labels)

# CODE GOES HERE TO CENTER X-AXIS LABELS...

# Render plot:
plt.show()

这是我正在寻找的结果

【问题讨论】:

标签: python matplotlib


【解决方案1】:

使用 DavidG 发布的线程中建议的次要刻度应该可以工作。下面是我针对您的特定问题进行了调整的 MWE,强制主要刻度出现在每个月的第一天,并使用次要刻度将标签放置在主要刻度之间:

import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np
import datetime

# Generate some data for example :

yr = 2014
fig, ax = plt.subplots()

x0 = datetime.datetime(yr, 1, 1)
x = np.array([x0 + datetime.timedelta(days=i) for i in range(365)])

y1 = np.sin(2*np.pi*np.arange(365)/365) + np.random.rand(365)/5
y2 = np.sin(2*np.pi*np.arange(365)/365) + np.random.rand(365)/5 - 1

# Draw high and low temperatures lines :

ax.plot(x, y1, color='#c83c34')
ax.plot(x, y2, color='#28659c')
ax.fill_between(x, y2, y1, facecolor='#daecfd', alpha=0.5)

# Force the major ticks position on the first of each month and hide labels:

xticks = [datetime.datetime(yr, i+1, 1) for i in range(12)]
xticks.append(datetime.datetime(yr+1, 1, 1))
ax.set_xticks(xticks)
ax.tick_params(axis='both', direction='out', top=False, right=False)
ax.axis([xticks[0], xticks[-1], -2.5, 1.5])
ax.set_xticklabels([])

# CODE GOES HERE TO CENTER X-AXIS LABELS...

labels = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
          'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
mticks = ax.get_xticks()
ax.set_xticks((mticks[:-1]+mticks[1:])/2, minor=True)
ax.tick_params(axis='x', which='minor', length=0)
ax.set_xticklabels(labels, minor=True)
fig.tight_layout()

plt.show()

导致:

【讨论】:

    【解决方案2】:

    在绘图时直接使用日期通常是有意义的。因此,与其手动设置标签的固定位置,不如使用matplotlib.dates 定位器。要将刻度定位在月中,可以选择当月的 15 日,

    matplotlib.dates.MonthLocator(bymonthday=15)
    

    一个完整的例子:

    import pandas as pd
    import matplotlib.pyplot as plt
    import matplotlib.dates as mdates
    import matplotlib.ticker as mticker
    import random
    
    df = pd.DataFrame(random.sample(range(10000),8760),
                      index = pd.date_range(start ='2013-01-01 00:00:00',
                                            end ='2013-12-31 23:30:00',
                                            freq='1H'),
                      columns =['value'])
    
    fig, ax = plt.subplots()
    ax.plot(df.index, df['value'])
    ax.set_xlim(pd.Timestamp('2013-01-01 00:00:00'), pd.Timestamp('2013-12-31 23:30:00'))
    
    months = mdates.MonthLocator(bymonth =(1,6,12), bymonthday=15 )
    allmonths = mdates.MonthLocator()
    m_fmt = mdates.DateFormatter('%b')
    ax.xaxis.set_major_locator(allmonths)
    ax.xaxis.set_minor_locator(months)
    
    ax.xaxis.set_major_formatter(mticker.NullFormatter())
    ax.xaxis.set_minor_formatter(m_fmt)
    ax.tick_params(axis="x", which="minor", length=0)
    plt.show()
    

    【讨论】:

    • 这对于这个简化的示例非常有效。我有一个更复杂的子图场景,它不起作用......将发布另一个问题。
    • 我的相关问题在这里:stackoverflow.com/questions/52037844/…
    【解决方案3】:

    几乎,Jean-Sébastien。除了上个月,它看起来一切都很完美。它不显示。

    您的解决方案稍作调整:

    fig, ax = plt.subplots()
    
    # Draw high and low temperatures lines:
    plt.plot(x, y1, color = '#c83c34')
    plt.plot(x, y2, color = '#28659c')
    
    # Fill area between lines:
    plt.gca().fill_between(x,
                           y2, y1,
                           facecolor='#daecfd',
                           alpha=0.5)
    
    # Force major ticks on a monthly time scale only:
    locator = mpl.dates.MonthLocator()
    ax.xaxis.set_major_locator(locator)
    
    # Hide major labels and set axis limits:
    ax.set_xticklabels([])
    ax.tick_params(axis='both', direction='out')
    ax.axis(xmin=datetime.datetime(2014, 1, 1),
            xmax=datetime.datetime(2014, 12, 31),
            ymin=-50, ymax=50)
    
    labels = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
              'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
    
    mticks = ax.get_xticks()
    ax.set_xticks((mticks[:-1]+mticks[1:])/2, minor=True)
    ax.tick_params(axis='x', which='minor', length=0)
    ax.set_xticklabels(labels, minor=True)
    
    plt.show()
    

    我得到的情节是这样的:

    关于在 x 轴标签中包含 12 月需要什么的任何线索?无论如何,非常感谢。

    【讨论】:

    • 需要将xmax设置为(2015, 1, 1)
    • 我已经试过了。情况变得更糟,仅从 1 月到 6 月绘制了五个刻度
    • 我的设置一切正常。如果在设置轴限制后添加plt.draw(),它会改变什么吗?
    • 可能是渲染器或matplotlib版本的原因。否则我看不出有什么问题。我将发布一个替代解决方案,其中包含厚标记的硬编码位置,1 秒。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多