我正在尝试使用 Python 中的 Plotly 创建并排树状图子图。我已经成功创建了子图并向每个子图添加了树状图,但我正在努力用线条连接两个树状图之间的相应提示。
这是我的代码的一个最小示例:
import plotly.figure_factory as ff
from plotly.subplots import make_subplots
import numpy as np
X1 = np.random.rand(10, 12)
X2 = np.random.rand(10, 12)
names = ['Jack', 'Oxana', 'John', 'Chelsea', 'Mark', 'Alice', 'Charlie', 'Rob', 'Lisa', 'Lily']
# Create dendrograms
fig1 = ff.create_dendrogram(X1, orientation='right', labels=names)
fig2 = ff.create_dendrogram(X2, orientation='left', labels=names)
# Create subplots with 1 row and 2 columns
#fig = make_subplots(rows=1, cols=2, subplot_titles=("Dendrogram 1", "Dendrogram 2"))
# Add traces from each dendrogram to respective subplots
#fig.add_traces(fig1['data'], rows=1, cols=1)
#fig.add_traces(fig2['data'], rows=1, cols=2)
# Calculate coordinates for the lines
#line_x = [0, 0.5, 1]
#line_y = [0, 0.5, 1]
# Create subplots with 1 row and 2 columns
fig = make_subplots(rows=1, cols=2)
# Add the first dendrogram to the first subplot
for trace in fig1['data']:
fig.add_trace(trace, row=1, col=1)
# Add the second dendrogram to the second subplot
for trace in fig2['data']:
fig.add_trace(trace, row=1, col=2)
# Add lines between corresponding tips
for i in range(len(names)):
fig.add_shape(type="line",
x0=0.5, y0=fig1['layout']['yaxis']['tickvals'][i],
x1=1.5, y1=fig2['layout']['yaxis']['tickvals'][i],
line=dict(color="black", width=1))
# Update layout
fig.update_layout(height=600, width=800, showlegend=False, title_text="Dendrograms Side by Side")
# Show plot
fig.show()
在此代码中,我尝试使用 add_shape 将两个树状图之间的尖端与线条连接起来,但线条似乎没有正确定位。如何正确连接树状图之间的相应提示?当我绘制子图时,我在显示提示标签时也遇到问题。
我也喜欢尝试在额外的子图中绘制链接
import plotly.figure_factory as ff
from plotly.subplots import make_subplots
import numpy as np
# Generating random data for X1, X2, and X3
X1 = np.random.rand(10, 12)
X2 = np.random.rand(10, 12)
X3 = np.random.rand(10, 12)
names = ['Jack', 'Oxana', 'John', 'Chelsea', 'Mark', 'Alice', 'Charlie', 'Rob', 'Lisa', 'Lily']
# Create dendrograms for X1, X2, and X3
fig1 = ff.create_dendrogram(X1, orientation='right')
fig2 = ff.create_dendrogram(X2, orientation='right')
fig3 = ff.create_dendrogram(X3, orientation='left')
# Create a new list of hover labels for fig1 and fig3 (right-oriented dendrograms)
hover_labels_fig1 = []
hover_labels_fig3 = []
for i in range(len(X1)):
for name in names:
hover_labels_fig1.append(name)
hover_labels_fig3.append(name)
# Add hover labels to each trace in fig1 and fig3
for trace in fig1['data']:
trace.hovertext = hover_labels_fig1
for trace in fig3['data']:
trace.hovertext = hover_labels_fig3
# Create subplots with increased width
fig = make_subplots(rows=1, cols=3, column_widths=[0.5, 0.1, 0.5])
# Add the first dendrogram to the first subplot
for data in fig1['data']:
fig.add_trace(data, row=1, col=1)
# Add the third dendrogram to the third subplot
for data in fig3['data']:
fig.add_trace(data, row=1, col=3)
# Add the link between the first and third plots in the second subplot
for i in range(len(names)):
fig.add_shape(type="line",
x0=0.5, y0=fig1['layout']['yaxis']['tickvals'][i],
x1=1.5, y1=fig3['layout']['yaxis']['tickvals'][i],
line=dict(color="black", width=1),
row=1, col=2)
# Update layout
fig.update_layout(height=600, width=1200, showlegend=False, title_text="Dendrograms Side by Side")
# Show plot
fig.show()
我也尝试过这个:
import plotly.figure_factory as ff
from plotly.subplots import make_subplots
import plotly.graph_objects as go
import numpy as np
np.random.seed(20240406) # Set random seed for reproducibility
# Generating random data for X1, X2, and X3
X1 = np.random.rand(10, 12)
X2 = np.random.rand(10, 12)
X3 = np.random.rand(10, 12)
names = ['Jack', 'Oxana', 'John', 'Chelsea', 'Mark', 'Alice', 'Charlie', 'Rob', 'Lisa', 'Lily']
# Create dendrograms for X1, X2, and X3
fig1 = ff.create_dendrogram(X1, orientation='right', labels=names)
fig3 = ff.create_dendrogram(X3, orientation='left', labels=names)
# Create hover labels for fig1 and fig3 (right-oriented dendrograms)
hover_labels_fig1 = []
hover_labels_fig3 = []
for i in range(len(X1)):
for name in names:
hover_labels_fig1.append(name)
hover_labels_fig3.append(name)
# Add hover labels to each trace in fig1 and fig3
for trace in fig1['data']:
trace.hovertext = hover_labels_fig1
for trace in fig3['data']:
trace.hovertext = hover_labels_fig3
# Create subplots with increased width
fig = make_subplots(rows=1, cols=3, column_widths=[0.4, 0.2, 0.4], horizontal_spacing=0)
# Add the first dendrogram to the first subplot
for data in fig1['data']:
fig.add_trace(data, row=1, col=1)
# Add the third dendrogram to the third subplot
for data in fig3['data']:
fig.add_trace(data, row=1, col=3)
# Use the tick values directly as y-values for the links
y_values_fig1 = fig1['layout']['yaxis']['tickvals']
y_values_fig3 = fig3['layout']['yaxis']['tickvals']
# Determine the minimum y-coordinate of the second dendrogram
min_y3 = min(y_values_fig3)
# Create dictionaries to map names to positions
left_positions = {name: idx for idx, name in enumerate(fig3['layout']['yaxis']['ticktext'])}
right_positions = {name: idx for idx, name in enumerate(fig1['layout']['yaxis']['ticktext'])}
# Store y-coordinate pairs for linking lines
linking_lines = []
for name in names:
if name in left_positions and name in right_positions:
idx_left = left_positions[name]
idx_right = right_positions[name]
linking_lines.append([y_values_fig1[idx_right], y_values_fig3[idx_left] - min_y3])
# Add the links between the first and third plots in the second subplot
for yy in linking_lines:
fig.add_trace(go.Scatter(
mode="lines",
x=[0.5, 1.5],
y=[yy[0], yy[1]],
line=dict(color="black", width=1)
), row=1, col=2)
# Update layout
fig.update_layout(height=600, width=1200, showlegend=False, title_text="Dendrograms Side by Side")
fig.update_xaxes(visible=False, row=1, col=2)
fig.update_yaxes(visible=False, row=1, col=2)
# Show plot
fig.show()
该图的内部结构是针对散点图以线模式构建的,因此也可以通过以线模式绘制来调整它。起点是左 y 轴,终点是右 y 轴。我用你的代码修改了它。我还隐藏了第二张图上的比例并消除了图之间的间距以使布局更清晰。
import plotly.figure_factory as ff
from plotly.subplots import make_subplots
import plotly.graph_objects as go
import numpy as np
np.random.seed(20240406)
# Generating random data for X1, X2, and X3
X1 = np.random.rand(10, 12)
X2 = np.random.rand(10, 12)
X3 = np.random.rand(10, 12)
names = ['Jack', 'Oxana', 'John', 'Chelsea', 'Mark', 'Alice', 'Charlie', 'Rob', 'Lisa', 'Lily']
# Create dendrograms for X1, X2, and X3
fig1 = ff.create_dendrogram(X1, orientation='right')
fig2 = ff.create_dendrogram(X2, orientation='right')
fig3 = ff.create_dendrogram(X3, orientation='left')
# Create a new list of hover labels for fig1 and fig3 (right-oriented dendrograms)
hover_labels_fig1 = []
hover_labels_fig3 = []
for i in range(len(X1)):
for name in names:
hover_labels_fig1.append(name)
hover_labels_fig3.append(name)
# Add hover labels to each trace in fig1 and fig3
for trace in fig1['data']:
trace.hovertext = hover_labels_fig1
for trace in fig3['data']:
trace.hovertext = hover_labels_fig3
# Create subplots with increased width
fig = make_subplots(rows=1, cols=3, column_widths=[0.4, 0.2, 0.4], horizontal_spacing=0)
# Add the first dendrogram to the first subplot
for data in fig1['data']:
fig.add_trace(data, row=1, col=1)
# Add the third dendrogram to the third subplot
for data in fig3['data']:
fig.add_trace(data, row=1, col=3)
# Add the link between the first and third plots in the second subplot
for i in range(len(names)):
fig.add_trace(go.Scatter(
mode="lines",
x=[0.5, 1.5],
y=[fig1['layout']['yaxis']['tickvals'][i],fig3['layout']['yaxis']['tickvals'][i]],
line=dict(color="black", width=1)
), row=1, col=2)
# Update layout
fig.update_layout(height=600, width=1200, showlegend=False, title_text="Dendrograms Side by Side")
fig.update_xaxes(visible=False, row=1, col=2)
fig.update_yaxes(visible=False, row=1, col=2)
# Show plot
fig.show()