4

我有一个 3D 散点图,它在其中一个平面上为每个日期绘制 2 个点。我问过如何在每对点之间画一条线,并收到了我很感激的答案。我现在想要的是绘制一个 BAR 或 RECTANGLE 来连接点,而不仅仅是一条线。

是该图目前的样子,但我希望它看起来有点像matplolib 文档中的 3D 条形演示中的图,除了条形“浮动”而不是锚定到轴上。

我尝试过使用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()
4

3 回答 3

5

我认为使用 PolyCollection 会更容易。这接近你所追求的吗?

在此处输入图像描述

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()
于 2012-05-15T14:23:24.980 回答
2

您应该能够混合使用:

matplolib 文档中的 3D 条形演示

条形堆叠示例

即在 3D 图形中绘制条形图,但使用“底部”参数设置条形图的起始高度。

亚历克西斯

于 2012-05-15T12:44:23.223 回答
2

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

我使用了 Alexis 的提示来使用 'zdir' 属性。

至于错误的平面问题,你可以用参数 zdir 来修复它,例如 ax.bar(dates, highs,zdir='y',bottom=highs, zs=0, color = 'b') – Alexis

起初,它生成的柱线高度是应有的两倍,因为它是从底部测量的(即“低点”值),然后向其添加一个高度(从“高点”值开始)。

所以我最终引入了一个新的列表,“位移”,它测量每个高点和每个低点之间的距离(在这个过程中我发现我的低点和高点交换了。呃,对不起)。所以现在我正在绘制“位移”而不是高点。

我在 Alexis 的行中添加了宽度、对齐方式、edgecolor 和 alpha(用于透明度);然后加厚了 ax.scatter 图的标记。现在代码可以工作了(嗯,几乎,除了第 4 条上的箭头高于它应该是......嗯)

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

这是结果:

阴谋

于 2012-05-16T10:58:13.693 回答