如何使xtick与Python matplotlib中的xlim不同?

jet*_*orz 2 python matplotlib

我想使用Python逐年绘制动态图。

X轴的轴将是12个月,在Matplotlib中该过程将是一个barh,如下代码所示:

import random
import datetime
import matplotlib.pyplot as plt

def get_percent():
    today = datetime.date.today()
    start = datetime.date(today.year, 1, 1)
    diff = today - start
    percent = diff.days/365.0
    return percent

fig = plt.figure(figsize=(8,2))
ax = fig.add_subplot(1,1,1)
percent = get_percent()

ax.axis([0, 12, 0, 1])
month = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug','Sep', 'Nov', 'Dec']
ax.set_xticklabels(month)
ax.set_xlim(0, 100)
ax.barh(bottom=0.5,width=int(percent*100),height=0.2)

plt.show()
plt.close()
Run Code Online (Sandbox Code Playgroud)

但是在情节之后,xtick显示7月是一年中的100%,这不是我想要的。

在此处输入图片说明

我搜索了matplotlib的文档,但没有找到答案:(。我如何使x轴刻度线显示Jan-Dec,而barh显示年份的百分比?

Mic*_*off 6

如何使xtick与Python matplotlib中的xlim不同?

这是不可能的。xtick本质上是您xlim(您的x范围)内的子域。“提示”无非是您选择的极限范围内的离散点Locator。在视觉上,刻度线以两种方式向您显示:第一,我认为是正交线,它给“刻度线”起了名字,第二,它附近显示的值。但是,该值如何呈现给用户,又取决于所选的Formatter。设置自定义标签归结为使用,FixedFormatter它仅返回本地刻度索引的任意标签。

有关更多详细信息,请参见https://matplotlib.org/api/ticker_api.html


错在你的代码?

fig = plt.figure(figsize=(8,2))
ax = fig.add_subplot(1,1,1)
ax.axis([0, 12, 0, 1])
ax.get_xticks()
# returns array([  0.,   2.,   4.,   6.,   8.,  10.,  12.])
Run Code Online (Sandbox Code Playgroud)

设置限制,以使其精确产生6个刻度:

图片1

如果现在分配的自定义标签比实际的刻度数更多,那么多余的标签将被忽略。这是您遇到的行为。

好笑的东西。如果您随后设置自定义标签并增加刻度线数量(并以此增加范围),会发生什么情况?

fig = plt.figure(figsize=(8,2))
ax = fig.add_subplot(1,1,1)
ax.axis([0, 12, 0, 1])
ax.set_xticklabels(['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep','Oct', 'Nov', 'Dec'])
ax.set_xticks(range(24))  # [0, 1, ..., 22, 23]
ax.get_xlim()
# returns (0.0, 23.0)
Run Code Online (Sandbox Code Playgroud)

它会增加您的x范围(!),并且对于超过12个滴答声都不会显示任何标签:

图片2

请注意,您还可以在设置标签后显式更改x范围。但是,因为底层的Formatter并不真正关心具体的值,而是本地的刻度索引和新的x范围具有相同的刻度数,所以您无法真正看到发生了什么。设置完成后xlim(0, 100)您的蜱实际上是[0, 20, 40, ... 100]和不是[0 ... 12]了。这很容易导致错误,这就是为什么您应该始终尝试在一个域中进行一致操作的原因(0-12个月,0-100 / 0-1%)。


解决问题:选择域!

对于此示例,我选择月份作为我们的域,这意味着我们在0到12之间进行操作。请注意,下限0对应于1月1日,上限12对应于12月31日。现在,我们可以将月度滴答声(等于ax.set_xticks(range(12)))左对齐,或将它们放在相应月份的中间(等于import numpy as np; ax.set_xticks(np.arange(0, 12, 1) + 0.5))。当我们设置要(0, 12)修改的限制时,刻度不会改变。

使用月份作为域还意味着您的百分比值(0, 1)是相对于(0, 12)而非(0, 100)。因此,您必须将其乘以12以获得所需的宽度。

放在一起:

import random
import datetime
import matplotlib.pyplot as plt

def get_percent():
    today = datetime.date.today()
    start = datetime.date(today.year, 1, 1)
    diff = today - start
    percent = diff.days/365.0
    return percent

fig = plt.figure(figsize=(8,2))
ax = fig.add_subplot(1,1,1)
percent = get_percent()

ax.axis([0, 12, 0, 1])
month = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dec']
ax.set_xticks(range(12))  # ticks placed on [0, 1, ..., 11]
ax.set_xticklabels(month)
ax.barh(bottom=0.5,width=int(percent*12),height=0.2)

plt.show()
plt.close()
Run Code Online (Sandbox Code Playgroud)

情节

当您int在设置钢筋宽度时也删除了类型转换时,会收到以下结果:

浮动图

PS原谅我说“ Okt”而不是“ Oct”。那是我德国人的灵魂.. :)