【问题标题】:Trouble working with 3 ax objects on the same subplot在同一个子图上处理 3 个 ax 对象时遇到问题
【发布时间】:2017-12-11 01:55:12
【问题描述】:

代码:

import matplotlib.pyplot as plt
import pandas as pd
from numpy import arange
%matplotlib inline

avg_discount = pd.read_json('{"Date":{"0":1498694400000,"1":1498780800000,"2":1498867200000,"3":1498953600000,"4":1499040000000},"Discount":{"0":0.2136567047,"1":0.2186422586,"2":0.2171303955,"3":0.2273395644,"4":0.2285249182}}')
auth_counts = pd.read_json('{"index":{"0":"False","1":"True"},"authorized":{"0":155,"1":22}}')
violation_counts = pd.read_json('{"index":{"0":"False","1":"True"},"violations":{"0":55,"1":7}}')

fig = plt.figure()
ax1 = fig.add_subplot(1,1,1, label='1')
ax2 = ax1.twinx() #tried .twiny() but didn't work as desired
ax3 = fig.add_subplot(1,1,1, label='2', frame_on=False)
bar_positions = arange(2) + 0.75
ax1.bar(bar_positions, auth_counts['authorized'],0.5, color='#b0c4de')
ax1.xaxis.tick_top()
tick_positions = range(1,3)
ax1.set_xticks(tick_positions)
ax1.set_xticklabels(['Unauthorized','Authorized'])
ax2.bar(bar_positions, [55,7], 0.5)
ax2.set_ylim([1,160])
ax2.tick_params(axis='both', top='off', right='off', labelright='off')
ax3.plot(avg_discount['Date'], avg_discount['Discount'], color='r', marker='o')
ax3.tick_params(axis='both', left='off', top='off', right='off',labelleft='off')
ax3.set_xticklabels([val.day for val in avg_discount['Date']], rotation=90)
plt.show()

结果:

数据解释: - ax1 代表两个不同的组及其计数。 ax2 代表执行了某个动作的那两个组。 ax3 添加了一条统计趋势线,用于定义这些组的成员所采取的行动。

问题: - x 轴和相关数据点未与线图 ax3 对齐。另外,我想整齐地显示日期,但决定显示日期。任何关于如何更好地表示这些数据的建议将不胜感激。 - 虽然我设法让两个条形图重叠,但它们不再整齐地间隔开。我只能假设这是因为 matplotlib 试图找到一个满足所有 3 个图表的 xlimit,但是当我编辑所有 3 到 10 个图表的 xlimit 时,ax3 说限制超出了范围。

预期输出: - 我正在寻找的输出应该看起来有点类似于第一个条形图的输出。第 2 个条形图覆盖在第 1 个条形图上,线条绘制在图中。

【问题讨论】:

  • "neatly " 不是正确的问题描述。看了两遍问题,还是不知道是什么问题。你能准确描述一下情节有什么问题以及它应该是什么样子吗?
  • @ImportanceOfBeingErnest 我已经编辑了我的问题。根据我的理解,将 x 刻度设置为 0.75 和 1.5,宽度为 0.5 将导致第一个条形图从 x 轴上的 0.75 开始并以 1.25 结束,第二个从 1.5 开始并以 2 结束。我希望保持两边的边距。
  • 尝试运行您的代码会出错。你能提供一个minimal reproducible example 的问题吗?
  • @ImportanceOfBeingErnest 完成。

标签: python pandas matplotlib


【解决方案1】:

您可以将条形位置设置为某个整数,例如01,这样可以更轻松地处理间距。如果条形图居中对齐align="center" 并且宽度为 0.8,则它的范围从 -0.4 到 0.4,或从 0.6 到 1.4。将 xlim 设置为 [-1,2] 会在条形周围留出足够的空间。当然,您可以根据自己的喜好选择其他值。

要格式化日期轴,您可以使用 matplotlib 日期定位器和格式化程序(另见 the dates example)。

import matplotlib.pyplot as plt
import matplotlib.dates
import pandas as pd
from numpy import arange
#%matplotlib inline

avg_discount = pd.read_json('{"Date":{"0":1498694400000,"1":1498780800000,"2":1498867200000,"3":1498953600000,"4":1499040000000},"Discount":{"0":0.2136567047,"1":0.2186422586,"2":0.2171303955,"3":0.2273395644,"4":0.2285249182}}')
auth_counts = pd.read_json('{"index":{"0":"False","1":"True"},"authorized":{"0":155,"1":22}}')
violation_counts = pd.read_json('{"index":{"0":"False","1":"True"},"violations":{"0":55,"1":7}}')

fig = plt.figure()
ax1 = fig.add_subplot(1,1,1, label='1')
ax2 = ax1.twinx() 
ax3 = fig.add_subplot(1,1,1, label='2', frame_on=False)

bar_positions = arange(2)
ax1.bar(bar_positions, auth_counts['authorized'],0.8, color='#b0c4de', align="center")
ax1.xaxis.tick_top()
tick_positions = range(1,3)
ax1.set_xticks(bar_positions)
ax1.set_xticklabels(['Unauthorized','Authorized'])
ax2.bar(bar_positions, [55,7], 0.8, align="center")
ax2.set_ylim([1,160])
ax2.set_xlim([-1,2]) # set xlim manually, if wanted

ax2.tick_params(axis='both', top='off', right='off', labelright='off')
ax3.plot(avg_discount['Date'], avg_discount['Discount'], color='r', marker='o')
ax3.tick_params(axis='both', left='off', top='off', right='off',labelleft='off')
plt.setp(ax3.get_xticklabels(), rotation=60, ha="right")
ax3.xaxis.set_major_locator(matplotlib.dates.DayLocator())
ax3.xaxis.set_major_formatter(matplotlib.dates.DateFormatter("%Y-%m-%d"))

plt.show()

【讨论】:

  • 我完全复制粘贴了您的代码,并得到了我添加到原始问题中的结果。我的线图从我的 xlimit 开始,没有给出您发布的图像中显示的缓冲区。无论我将 xlimit 切换到什么,它总是从头开始并一直延伸到 x 轴。
  • 那么您是否要为线图设置此边距?
  • 你发布的图片是我想要我的样子的随地吐痰的图像,但即使玩 xlim 也无法让我的图片看起来像那张照片。
  • 好的,因为你可能有一个旧版本的matplotlib,你需要添加ax3.margins(x=0.05)。这会在 x 轴的两端增加 5% 的边距。
猜你喜欢
  • 1970-01-01
  • 2022-01-03
  • 2020-08-15
  • 2017-03-01
  • 2020-02-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多