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

时间:2017-04-13 12:38:38

标签: 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()

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

enter image description here

我搜索了matplotlib的文档,但没有找到答案:(。我怎样才能使x轴刻度显示1月 - 12月,而barh显示年份的百分比?

2 个答案:

答案 0 :(得分:4)

  

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

这是不可能的。 xtick基本上是xlim(您的x范围)内的子域。 "蜱"只不过是你所选择的Locator产生的极限范围内的离散点。在视觉上,刻度线以两种方式呈现给你:第一,小正交线,我认为它给出了" tick"它的名字,第二个,显示在它附近的值。但是,如何将值呈现给用户又取决于所选择的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.])

设置限制如何生成 6 刻度:

Image 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)

它会增加你的x范围(!)并且只显示超过12个刻度的标签:

Image 2

请注意,您还在设置标签后明确更改了x范围。但是因为底层的Formatter并不真正关心具体的值,而是本地的滴答索引和新的x-range有相同数量的滴答,你无法真正看到发生了什么。设置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()

Plot

设置条形宽度时,如果同时删除类型转换为int,则会收到以下结果:

Float Plot

P.S。原谅我" Okt"而不是" 10月"。那是我的德国灵魂在工作.. :))

答案 1 :(得分:0)

当然,更简单的方法是在轴上创建数月的图表。

在这里,问题是matplotlib不知道在哪个位置绘制字符串" 2月"。因此,从标签开始,您还需要设置xtick位置。 这可以完成,例如使用

ax.set_xticks(numpy.linspace(0,365,13)/365.*100)

我们使用numpy。您也可以手动输入与月份相对应的天数,并获得更准确的结果,因为并非所有月份都具有相同的天数。

另一个问题是你在列表中忘了带十月。 : - )

完整代码:

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

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','Oct', 'Nov', 'Dec']
ax.set_xticks(np.linspace(0,365,13)/365.*100)
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()

enter image description here