2012-05-15 90 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