Мне нужно визуализировать некоторые сложные многомерные наборы данных, и предпочтительным выбором является использование модификации визуализации параллельной оси с использованием сложенных 2D-графиков, где каждый график отображает степень свободы/параметр модели, а точки данных, принадлежащие к одним и тем же наборам данных, должны быть взаимосвязаны по разным участкам. Прилагаю концептуальный набросок. Как я могу реализовать это в matplotlib
?
Сложенные 2D-графики с взаимосвязями в Matplotlib
Ответы (2)
Чтобы иметь общее представление, это может быть возможным решением в matplotlib с использованием Axes3D
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle, PathPatch
import mpl_toolkits.mplot3d.art3d as art3d
x = np.array([1,2,3])
y = np.array([2,3,1])
z = np.array([1,1,1])
fig = plt.figure(figsize=(6,6))
ax = fig.add_axes([0,0,1,1], projection='3d')
#plot the points
ax.scatter(x,y,z*0.4, c="r", facecolor="r", s=60)
ax.scatter(y,x,z*0.9, c="b", facecolor="b", s=60)
ax.scatter(x,y,z*1.6, c="g", facecolor="g", s=60)
#plot connection lines
ax.plot([x[0],y[0],x[0]],[y[0],x[0],y[0]],[0.4,0.9,1.6], color="k")
ax.plot([x[2],y[2],x[2]],[y[2],x[2],y[2]],[0.4,0.9,1.6], color="k")
#plot planes
p = Rectangle((0,0), 4,4, color="r", alpha=0.2)
ax.add_patch(p)
art3d.pathpatch_2d_to_3d(p, z=0.4, zdir="z")
p = Rectangle((0,0), 4,4, color="b", alpha=0.2)
ax.add_patch(p)
art3d.pathpatch_2d_to_3d(p, z=0.9, zdir="z")
p = Rectangle((0,0), 4,4, color="g", alpha=0.2)
ax.add_patch(p)
art3d.pathpatch_2d_to_3d(p, z=1.6, zdir="z")
ax.set_aspect('equal')
ax.view_init(13,-63)
ax.set_xlim3d([0,4])
ax.set_ylim3d([0,4])
ax.set_zlim3d([0,2])
plt.savefig(__file__+".png")
plt.show()
Обновить
Возможно создание трех разных осей. Нужно добавить оси и сделать верхние прозрачными (ax2.patch.set_alpha(0.)
). Затем нужно отключить сетку (ax.grid(False)
), а панели и линии, которые нам не нужны, сделать невидимыми.
Однако я понятия не имею, как нарисовать связь между осями. 2D-подход matplotlib.patches.ConnectionPatch
не работает для 3D-осей.
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle
import mpl_toolkits.mplot3d.art3d as art3d
x = np.array([1,2,3])
y = np.array([2,3,1])
z = np.array([0,0,0])
fig = plt.figure(figsize=(6,6))
ax = fig.add_axes([0,0,1,1], projection='3d')
ax2 = fig.add_axes([0.0,0.24,1,1], projection='3d')
ax2.patch.set_alpha(0.)
ax3 = fig.add_axes([0.0,0.48,1,1], projection='3d')
ax3.patch.set_alpha(0.)
#plot the points
ax.scatter(x,y,z, c="r", facecolor="r", s=60)
ax2.scatter(y*4,x*4,z, c="b", facecolor="b", s=60)
ax3.scatter(x*100,y*100,z, c="g", facecolor="g", s=60)
#plot connection lines
#ax.plot([x[0],y[0],x[0]],[y[0],x[0],y[0]],[0.4,0.9,1.6], color="k")
#ax.plot([x[2],y[2],x[2]],[y[2],x[2],y[2]],[0.4,0.9,1.6], color="k")
#plot planes
p = Rectangle((0,0), 4,4, color="r", alpha=0.2)
ax.add_patch(p)
art3d.pathpatch_2d_to_3d(p, z=0, zdir="z")
p = Rectangle((0,0), 16,16, color="b", alpha=0.2)
ax2.add_patch(p)
art3d.pathpatch_2d_to_3d(p, z=0, zdir="z")
p = Rectangle((0,0), 400,400, color="g", alpha=0.2)
ax3.add_patch(p)
art3d.pathpatch_2d_to_3d(p, z=0, zdir="z")
ax.set_aspect('equal')
ax2.set_aspect('equal')
ax3.set_aspect('equal')
ax.view_init(13,-63)
ax2.view_init(10,-63)
ax3.view_init(8,-63)
ax.set_xlim3d([0,4])
ax.set_ylim3d([0,4])
ax.set_zlim3d([0,2])
ax2.set_xlim3d([0,16])
ax2.set_ylim3d([0,16])
ax2.set_zlim3d([0,2])
ax3.set_xlim3d([0,400])
ax3.set_ylim3d([0,400])
ax3.set_zlim3d([0,2])
ax.grid(False)
ax2.grid(False)
ax3.grid(False)
def axinvisible(ax):
for zax in (ax.w_zaxis, ax.w_xaxis, ax.w_yaxis):
zax.pane.set_visible(False)
if zax == ax.w_zaxis:
zax.line.set_visible(False)
for ll in zax.get_ticklines()+zax.get_ticklabels():
ll.set_visible(False)
axinvisible(ax)
axinvisible(ax2)
axinvisible(ax3)
# setting a ConnectionPatch does NOT work
from matplotlib.patches import ConnectionPatch
con = ConnectionPatch(xyA=(2,2), xyB=(2,2),
coordsA='data', coordsB='data',
axesA=ax, axesB=ax2,
arrowstyle='->', clip_on=True)
ax2.add_artist(con) # artist is not shown :-(
plt.show()
person
ImportanceOfBeingErnest
schedule
18.12.2016
Спасибо. Однако прямоугольники, которые я указал выше, должны быть разными плоскостями/осями данных. Это означает, что они представляют разные параметры и, таким образом, представляют точки в разных пространствах. Поэтому я считаю, что есть как минимум две проблемы: (i) рисовать оси в виде стопки (должно быть относительно легко); (ii) соединить точки по разным осям (это будет сложно, потому что единственный способ - иметь метрику, которая включает все точки...)
- person maurizio; 18.12.2016
Я еще не решил проблему сложенных графиков, которая должна быть относительно прямой, но для соединений между графиками
matplotlib.patches.ConnectionPatch
должен помочь, хотя в документе не сказано, работает ли этот метод на Axes3D
объектах...
- person maurizio; 20.12.2016
Я решил проблему сложенных графиков (см. обновление). Но я понятия не имею, как их соединить.
- person ImportanceOfBeingErnest; 21.12.2016
Спасибо, это направлено в том направлении, которое я хотел! К сожалению, я вижу, что
ConnectionPatch
не работает ... Позвольте мне посмотреть, собирается ли кто-нибудь еще комментировать и / или некоторые люди из matplotlib
хотят высказать свои идеи, прежде чем одобрить ваш ответ.
- person maurizio; 21.12.2016
На самом деле это может быть не реализовано. Если я заменю
ax.add_patch
на ваш последний экземпляр ax2.add_artist
, я получу следующее: AttributeError: 'ConnectionPatch' object has no attribute 'do_3d_projection'
.
- person maurizio; 21.12.2016
На самом деле у меня есть еще один вопрос по этой теме, поскольку
projection='3d'
в настоящее время не задокументировано как допустимое ключевое слово (см. matplotlib.org/api/figure_api.html). Что по умолчанию projection
? 'rectilinear'
Я полагаю, не так ли?
- person maurizio; 22.12.2016
Не понимаю, как этот вопрос относится к теме. В принципе вы правы, в исходном коде вы найдете где-то
if projection is None: projection = 'rectilinear'
, но если вы хотите узнать больше, я предлагаю задать новый вопрос об этом, на который я смогу ответить более подробно.
- person ImportanceOfBeingErnest; 22.12.2016
@ImportanceOfBeingErnest очень хороший ответ! Можно ли складывать оси горизонтально, а не вертикально? Я имею в виду иметь горизонтальные оси X и вертикальные оси Y в 3 разных положениях?
- person Pincopallino; 26.04.2017
@Pincopallino Конечно, можно сделать то же самое, укладывая самолеты горизонтально. В первом решении это должно быть прямолинейно, просто с использованием вертикальных плоскостей. Во втором решении вам нужно будет найти хорошие параметры для положения осей. Я бы посоветовал вам выбрать один из двух вариантов, попытаться реализовать его и, если возникнет проблема, задать новый вопрос с четким описанием проблемы.
- person ImportanceOfBeingErnest; 26.04.2017
Решение может быть основано на 3D-возможностях matplotlib. Вы можете использовать Axes3D.plot_surface
для построения осей, а также пользовательские графики разброса и линии для остальных.
person
Andi
schedule
18.12.2016