2012-05-15 55 views
4

我有一个3D散点图,它的一个平面上绘制每个日期的2个点。我问过about how to draw a LINE between every pair of points,并收到了我很感谢的答案。我现在想要的是绘制一个BAR或RECTANGLE来连接点而不是一条线。在Python中的3D散点图中的两点之间绘制矩形或条形图matplotlib

Here's此时情节看起来像什么,但我希望它看起来有点像从3D bar demo from matplolib's docs的情节,除了条形“浮动”而不是固定在轴上。

我试过使用Axes3D.bar(正如matplotlib页面所述),但它希望我为每个小节提供一个“高度”而不是两个实际坐标,并且该高度将固定在轴上。

这是代码,任何帮助表示赞赏。

import matplotlib.pyplot 
from mpl_toolkits.mplot3d import Axes3D 

dates  = [20020514, 20020515, 20020516, 20020517, 20020520] 
highs  = [1135, 1158, 1152, 1158, 1163] 
lows  = [1257, 1253, 1259, 1264, 1252] 
upperLimits = [1125.0, 1125.0, 1093.75, 1125.0, 1125.0] 
lowerLimits = [1250.0, 1250.0, 1156.25, 1250.0, 1250.0] 

zaxisvalues0= [0, 0, 0, 0, 0] 
zaxisvalues1= [1, 1, 1, 1, 1] 
zaxisvalues2= [2, 2, 2, 2, 2] 

fig = matplotlib.pyplot.figure() 
ax = fig.add_subplot(111, projection = '3d') 

ax.plot(dates, zaxisvalues1, lowerLimits, color = 'b') 
ax.plot(dates, zaxisvalues2, upperLimits, color = 'r') 

for i,j,k,h in zip(dates,zaxisvalues0,lows,highs): 
    ax.plot([i,i],[j,j],[k,h],color = 'g') 

ax.scatter(dates, zaxisvalues0, highs, color = 'g', marker = "o") 
ax.scatter(dates, zaxisvalues0, lows, color = 'y', marker = "^") 

matplotlib.pyplot.show() 

回答

2

你应该能够作出之间的混合:

3D bar demo from matplolib's docs

Bar stacked example

即绘制酒吧在3D图形,但使用“底部“参数来设置你的酒吧的起始高度。

Alexis

+0

谢谢你的提示,但我不能得到它的工作。我尝试用原始代码替换Mark的for循环: ax.bar(dates,zaxisvalues2,highs) 但它是在错误的平面上绘制条形图。我尝试了zaxisvalue0和zaxisvalues1,我试着洗牌顺序,但目前为止没有运气。 – Zambi

+0

也许这就是你要找的[hist3D example](http://matplotlib.sourceforge.net/examples/mplot3d/hist3d_demo.html)。然后,您可以使用zpos来设置框的最低边缘(举例来说,获取hist3D示例并将_zpos = hist.flatten()_)的第16行更改。 – Alexis

+0

至于错误的飞机问题,您可以使用参数zdir修复它,例如_ax.bar(日期,高位,zdir ='y',底部=高位,zs = 0,颜色='b')_ – Alexis

5

我认为使用PolyCollection会更容易。这是接近你以后的?

enter image description here

import matplotlib.pyplot 
from mpl_toolkits.mplot3d import Axes3D 
from matplotlib.collections import PolyCollection 
import random 

dates  = [20020514, 20020515, 20020516, 20020517, 20020520] 
highs  = [1135, 1158, 1152, 1158, 1163] 
lows  = [1257, 1253, 1259, 1264, 1252] 
upperLimits = [1125.0, 1125.0, 1093.75, 1125.0, 1125.0] 
lowerLimits = [1250.0, 1250.0, 1156.25, 1250.0, 1250.0] 

zaxisvalues0= [0, 0, 0, 0, 0] 
zaxisvalues1= [1, 1, 1, 1, 1] 
zaxisvalues2= [2, 2, 2, 2, 2] 

fig = matplotlib.pyplot.figure() 
ax = fig.add_subplot(111, projection = '3d') 

ax.plot(dates, zaxisvalues1, lowerLimits, color = 'b') 
ax.plot(dates, zaxisvalues2, upperLimits, color = 'r') 

verts = []; fcs = [] 
for i in range(len(dates)-1): 
    xs = [dates[i],dates[i+1],dates[i+1],dates[i],dates[i]] # each box has 4 vertices, give it 5 to close it, these are the x coordinates 
    ys = [highs[i],highs[i+1],lows[i+1],lows[i], highs[i]] # each box has 4 vertices, give it 5 to close it, these are the y coordinates 
    verts.append(zip(xs,ys)) 
    fcs.append((random.random(),random.random(),random.random(),0.6)) 

poly = PolyCollection(verts, facecolors = fcs, closed = False) 
ax.add_collection3d(poly, zs=[zaxisvalues0[0]] * len(verts), zdir='y') # in the "z" just use the same coordinate 

ax.scatter(dates, zaxisvalues0, highs, color = 'g', marker = "o") 
ax.scatter(dates, zaxisvalues0, lows, color = 'y', marker = "^") 

matplotlib.pyplot.show() 
+0

谢谢。尽管这并不是我希望达到的目标,但您的代码真的让人大开眼界。我应该阅读PolyCollections类。非常感谢评论代码 - 它确实有帮助。通过返回到原始代码并在for循环中的ax.plot命令中添加“linewidth = 5”,我已经接近我想要的了。它画了一条线,但足够厚,看起来像一个酒吧/矩形。 – Zambi

1

感谢您的帮助亚历克西斯和马克。我认为现在已经解决了。

我已经使用Alexis的提示使用'zdir'属性。

至于错了飞机的问题,你可以用参数zdir修复它, 例如ax.bar(日期,高开低走,zdir = 'Y',底部=高点,ZS = 0,颜色=“B ') - Alexis

起初,它生成的条形高度是它们应该是的两倍,因为它是从底部测量(即“低”值),然后添加到它的高度(从'高点'值)。

所以我最终推出了一个新的名单'displacements',它用来度量每个high和low之间的距离(并且在这个过程中发现我有我的低点和高点交换,Duh,对不起)。所以现在我正在绘制'位移'而不是高点。

我添加到亚历克西斯'线的宽度,对齐,边缘颜色和alpha(透明度);然后加厚斧头散点图的标记。现在代码可以工作(除此之外,除了第四栏上的箭头高于它应该是...)嗯)

import matplotlib.pyplot 
from mpl_toolkits.mplot3d import Axes3D 

dates  = [20020514, 20020515, 20020516, 20020517, 20020520] 
lows  = [1135, 1158, 1152, 1158, 1163] 
highs  = [1257, 1253, 1259, 1264, 1252] 
upperLimits = [1125.0, 1125.0, 1093.75, 1125.0, 1125.0] 
lowerLimits = [1250.0, 1250.0, 1156.25, 1250.0, 1250.0] 

zaxisvalues0= [0, 0, 0, 0, 0] 
zaxisvalues1= [1, 1, 1, 1, 1] 
zaxisvalues2= [2, 2, 2, 2, 2] 

fig = matplotlib.pyplot.figure() 
ax = fig.add_subplot(111, projection = '3d') 

ax.plot(dates, zaxisvalues1, lowerLimits, color = 'b') 
ax.plot(dates, zaxisvalues2, upperLimits, color = 'r') 

ax.scatter(dates, zaxisvalues0, highs, color = 'g', marker = "^", linewidth=4) 
ax.scatter(dates, zaxisvalues0, lows, color = 'y', marker = "o", linewidth=4) 

displacements = [] 
for i in lows: 
    position = lows.index(i) 
    disp = highs[position] - i 
    displacements.append(disp) 

ax.bar(dates, displacements, zdir='y', bottom=lows, zs=0, width=0.2, align='center', alpha=0.6, edgecolor='k') 

matplotlib.pyplot.show() 

这是结果:

Plot

+0

Zambi,你的第四个箭头的最后一个问题来自你的for循环:你有低的重复值,所以lows.index(i)总是返回1forfor 1158.对于范围(len(lows))中的_for i的变化:\\ disp = highs [i] - lows [i] _ – Alexis

+0

谢谢Alexis。你刚刚救了我几个小时试图修复第四棒。非常感激。 – Zambi