matplotlib:使用 SHARED X 轴但 SEPARATE Y 轴值创建两个(堆叠)子图 [英] matplotlib: Creating two (stacked) subplots with SHARED X axis but SEPARATE Y axis values

查看:40
本文介绍了matplotlib:使用 SHARED X 轴但 SEPARATE Y 轴值创建两个(堆叠)子图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 Ubuntu 10.0.4 上使用 matplotlib 1.2.x 和 Python 2.6.5.我正在尝试创建一个由顶图和底图组成的单图.

I am using matplotlib 1.2.x and Python 2.6.5 on Ubuntu 10.0.4. I am trying to create a SINGLE plot that consists of a top plot and a bottom plot.

X 轴是时间序列的日期.顶部图包含数据的烛台图,底部图应由条形图组成 - 具有自己的 Y 轴(也在左侧 - 与顶部图相同).这两个图不应重叠.

The X axis is the date of the time series. The top plot contains a candlestick plot of the data, and the bottom plot should consist of a bar type plot - with its own Y axis (also on the left - same as the top plot). These two plots should NOT OVERLAP.

这里是我到目前为止所做的摘要.

Here is a snippet of what I have done so far.

datafile = r'/var/tmp/trz12.csv'
r = mlab.csv2rec(datafile, delimiter=',', names=('dt', 'op', 'hi', 'lo', 'cl', 'vol', 'oi'))

mask = (r["dt"] >= datetime.date(startdate)) & (r["dt"] <= datetime.date(enddate))
selected = r[mask]
plotdata = zip(date2num(selected['dt']), selected['op'], selected['cl'], selected['hi'], selected['lo'], selected['vol'], selected['oi'])

# Setup charting 
mondays = WeekdayLocator(MONDAY)        # major ticks on the mondays
alldays    = DayLocator()               # minor ticks on the days
weekFormatter = DateFormatter('%b %d')  # Eg, Jan 12
dayFormatter = DateFormatter('%d')      # Eg, 12
monthFormatter = DateFormatter('%b %y')

# every Nth month
months = MonthLocator(range(1,13), bymonthday=1, interval=1)

fig = pylab.figure()
fig.subplots_adjust(bottom=0.1)
ax = fig.add_subplot(111)
ax.xaxis.set_major_locator(months)#mondays
ax.xaxis.set_major_formatter(monthFormatter) #weekFormatter
ax.format_xdata = mdates.DateFormatter('%Y-%m-%d')
ax.format_ydata = price
ax.grid(True)

candlestick(ax, plotdata, width=0.5, colorup='g', colordown='r', alpha=0.85)

ax.xaxis_date()
ax.autoscale_view()
pylab.setp( pylab.gca().get_xticklabels(), rotation=45, horizontalalignment='right')

# Add volume data 
# Note: the code below OVERWRITES the bottom part of the first plot
# it should be plotted UNDERNEATH the first plot - but somehow, that's not happening
fig.subplots_adjust(hspace=0.15)
ay = fig.add_subplot(212)
volumes = [ x[-2] for x in plotdata]
ay.bar(range(len(plotdata)), volumes, 0.05)

pylab.show()

我已经使用上面的代码设法显示了两个图,但是,底部图有两个问题:

I have managed to display the two plots using the code above, however, there are two problems with the bottom plot:

  1. 它完全覆盖了第一个(顶部)图的底部-好像第二个图与第一个图在相同的画布"上绘制-我看不到发生在哪里/为什么.

  1. It COMPLETELY OVERWRITES the bottom part of the first (top) plot - almost as though the second plot was drawing on the same 'canvas' as the first plot - I can't see where/why that is happening.

它用自己的索引覆盖现有的 X 轴,X 轴值(日期)应该在两个图之间共享.

It OVERWRITES the existing X axis with its own indice, the X axis values (dates) should be SHARED between the two plots.

我的代码做错了什么?有人能发现是什么导致第二个(底部)图覆盖了第一个(顶部)图 - 我该如何解决这个问题?

What am I doing wrong in my code?. Can someone spot what is causing the 2nd (bottom) plot to overwrite the first (top) plot - and how can I fix this?

这是上面代码创建的图的屏幕截图:

Here is a screenshot of the plot created by the code above:

[]

按照hwlau的建议修改代码后,这是新的情节.比第一个更好,因为两个地块是分开的,但仍然存在以下问题:

After modifying the code as suggested by hwlau, this is the new plot. It is better than the first in that the two plots are separate, however the following issues remain:

  1. X轴应由两个图共享(即,仅在第二个[底部]图上显示X轴)

  1. The X axis should be SHARED by the two plots (i.e. the X axis should be shown only for the 2nd [bottom] plot)

第二个图的Y值似乎被错误地设置了

The Y values for the 2nd plot seem to be formmated incorrectly

我认为这些问题应该很容易解决,但是,我的 matplotlib fu 目前不是很好,因为我最近才开始使用 matplotlib 进行编程.任何帮助将不胜感激.

I think these issues should be quite easy to resolve however, my matplotlib fu is not great at the moment, as I have only recently started programming with matplotlib. any help will be much appreciated.

推荐答案

您的代码似乎有几个问题:

There seem to be a couple of problems with your code:

  1. 如果您使用 figure.add_subplots 和完整的subplot(nrows, ncols, plotNum) 的签名可能有更明显的是,您的第一个地块要求1行和1列,第二个图要求2行,1 列.因此,您的第一个图是填充整个图形.而不是 fig.add_subplot(111)后跟 fig.add_subplot(212)使用 fig.add_subplot(211),然后使用 fig.add_subplot(212).

  1. If you were using figure.add_subplots with the full signature of subplot(nrows, ncols, plotNum) it may have been more apparent that your first plot asking for 1 row and 1 column and the second plot was asking for 2 rows and 1 column. Hence your first plot is filling the whole figure. Rather than fig.add_subplot(111) followed by fig.add_subplot(212) use fig.add_subplot(211) followed by fig.add_subplot(212).

共享轴应使用 sharex = first_axis_instance

我整理了一个您应该可以运行的示例:

I have put together an example which you should be able to run:

import matplotlib.pyplot as plt
import matplotlib.ticker as mticker
import matplotlib.dates as mdates


import datetime as dt


n_pts = 10
dates = [dt.datetime.now() + dt.timedelta(days=i) for i in range(n_pts)]

ax1 = plt.subplot(2, 1, 1)
ax1.plot(dates, range(10))

ax2 = plt.subplot(2, 1, 2, sharex=ax1)
ax2.bar(dates, range(10, 20))

# Now format the x axis. This *MUST* be done after all sharex commands are run.

# put no more than 10 ticks on the date axis.  
ax1.xaxis.set_major_locator(mticker.MaxNLocator(10))
# format the date in our own way.
ax1.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))

# rotate the labels on both date axes
for label in ax1.xaxis.get_ticklabels():
    label.set_rotation(30)
for label in ax2.xaxis.get_ticklabels():
    label.set_rotation(30)

# tweak the subplot spacing to fit the rotated labels correctly
plt.subplots_adjust(hspace=0.35, bottom=0.125)

plt.show()

希望有帮助.

这篇关于matplotlib:使用 SHARED X 轴但 SEPARATE Y 轴值创建两个(堆叠)子图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆