无法在同一个子图上使用3个ax对象

时间:2017-07-06 21:45:28

标签: python pandas matplotlib

守则:

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

结果:

enter image description here

数据说明: - ax1代表两个不同的组及其计数。 ax2代表执行某项行动的两个群体。 ax3添加统计趋势线,定义这些组成员所采取的操作。

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

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

Expected Result

1 个答案:

答案 0 :(得分:1)

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

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

enter image description here

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