Рисование прямоугольника или полосы между двумя точками на трехмерном графике рассеяния в Python и matplotlib
У меня есть трехмерный график рассеяния, который на одной из его плоскостей отображает 2 точки для каждой даты. Я спросил о том, как провести линию между каждой парой точек, и получил ответ, за который я благодарен. Теперь я хочу нарисовать БАР или ПРЯМОУГОЛЬНИК, чтобы соединить точки, а не просто линию.
Вот как выглядит график на данный момент, но я хочу, чтобы он немного походил на график из демонстрации 3D-бара из документов Matplolib, за исключением того, что столбцы "плавают" вместо привязки к оси.
Я пытался использовать 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()
3 ответа
Я думаю, что будет проще использовать 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()
Вы должны быть в состоянии сделать смесь между:
3D бар демо из документации Матплолиба
а также
то есть рисовать бары на трехмерном графике, но используйте параметр "bottom", чтобы установить начальную высоту ваших баров.
Alexis
Спасибо за вашу помощь Алексис и Марк. Я думаю, что это разобрано сейчас.
Я использовал подсказку Alexis для использования свойства 'zdir'.
Что касается проблемы с неправильной плоскостью, вы можете исправить ее с помощью параметра zdir, например, ax.bar(даты, максимумы,zdir='y', нижние = максимумы, zs=0, цвет = 'b') - Alexis
Сначала он генерировал бары, которые в два раза выше, чем они должны быть, потому что он измерял снизу (т.е. значение "минимумы"), а затем добавлял к нему высоту (из значения "максимумы").
Поэтому я закончил тем, что ввел новый список, "смещения", который измеряет расстояние между каждым максимумом и каждым минимумом (и в процессе обнаружил, что мои минимумы и максимумы менялись местами. Дух, извините за это). Так что теперь я строю смещения, а не максимумы.
Я добавил к строке Алексея ширину, выравнивание, цвет кромки и альфа (для прозрачности); затем утолщенные маркеры для графиков топора. Теперь код работает (ну, почти, за исключением того, что стрелка на 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()
Это результат: