질문

import pandas as pd
import plotly.graph_objs as go
import plotly.express as px
import os

print("当前工作目录是:", os.getcwd())

示例数据
data = {
'group': ['Sample1', 'Sample1', 'Sample1', 'Sample2', 'Sample2', 'Sample2'],
'celltype': ['Type1', 'Type2', 'Type3', 'Type1', 'Type2', 'Type3'],
'n': [100, 200, 150, 120, 180, 130]
}
scedata = pd.DataFrame(data)

计算相对频率
celltype_ratio = scedata.groupby(['group', 'celltype'])['n'].sum().reset_index()
celltype_ratio['relative_freq'] = celltype_ratio.groupby('group')['n'].transform(lambda x: x / x.sum())

颜色调色板
mycolor = ['#efb306', '#7db954', '#852f88', '#4e54ac', '#0f8096']

堆叠柱状图函数
def create_stacked_bar(df):
fig = px.bar(df, x='relative_freq', y='group', color='celltype',
color_discrete_sequence=mycolor,
orientation='h',
labels={'relative_freq': '比例', 'group': '样本'},
title='细胞类型分布')
fig.update_layout(
xaxis_title='比例',
yaxis_title='样本',
legend_title='细胞类型'
)
return fig

类Sankey图可视化函数
def create_sankey_like_plot(df):
groups = df['group'].unique()
celltypes = df['celltype'].unique()

traces = []

for i, group in enumerate(groups):
group_data = df[df['group'] == group]

# 柱子
column_bar = go.Bar(
x=[group_data['relative_freq'].sum()],
y=[group],
orientation='h',
marker_color='lightgray',
width=0.5,
name=group
)
traces.append(column_bar)

# 细胞类型分段
bottom = 0
for j, celltype in enumerate(group_data['celltype']):
value = group_data[group_data['celltype'] == celltype]['relative_freq'].values[0]

segment = go.Bar(
x=[value],
y=[group],
orientation='h',
marker_color=mycolor[j % len(mycolor)],
width=0.5,
base=bottom,
name=celltype
)
traces.append(segment)

bottom += value

# 布局
layout = go.Layout(
title='细胞类型分布(Sankey风格)',
xaxis=dict(title='比例'),
yaxis=dict(title='样本'),
barmode='stack',
height=400,
width=800
)

fig = go.Figure(data=traces, layout=layout)
return fig
查看全部
模拟 Alluvial 图风格的调整
def create_alluvial_like_plot(df):
fig = go.Figure()

# 绘制每个细胞类型的流动
for idx, group in enumerate(df['group'].unique()):
group_data = df[df['group'] == group]
bottom = 0
for i, celltype in enumerate(group_data['celltype']):
value = group_data[group_data['celltype'] == celltype]['relative_freq'].values[0]
fig.add_trace(go.Scatter(
x=[value, value],
y=[group, group],
mode='lines+markers',
line=dict(width=5, color=mycolor[i]),
name=celltype
))
fig.update_layout(
title='冲击桑基图(Alluvial风格)',
xaxis_title='比例',
yaxis_title='样本',
showlegend=True,
height=400,
width=800
)

return fig
查看全部
生成图表
stacked_bar = create_stacked_bar(celltype_ratio)
sankey_like = create_sankey_like_plot(celltype_ratio)
alluvial_like = create_alluvial_like_plot(celltype_ratio)

保存为HTML
stacked_bar.write_html("stacked_bar_chart.html")
sankey_like.write_html("sankey_like_plot.html")
alluvial_like.write_html("alluvial_like_plot.html")

print("图表已生成为 stacked_bar_chart.html, sankey_like_plot.html 和 alluvial_like_plot.html")
修改代码,将同类型的的type链接起来,例如这样操作
#冲击桑基图
ggplot(Ratio, aes(x =group, y= relative_freq, fill = celltype,
stratum=celltype, alluvium=celltype)) +
geom_col(width = 0.5, color='black')+
geom_flow(width=0.5,alpha=0.4, knot.pos=0)+
theme_classic() +
labs(x='Sample',y = 'Ratio')+
coord_flip()+
scale_fill_manual(values = mycolor)
,请优化代码实现

사고

连接单一细胞类型

用户希望通过优化Python代码,将相同的单一细胞类型跨群体连接起来,类似于R语言中的桑基图。

调整数据可视化

我正在将Python中的Plotly代码调整为使用Python创建类似R中ggplot与ggalluvial包的Alluvial图效果。

迈入绘图领域

正在探索利用Plotly创造类似于冲击桑基图的图形,逐步设计和调整函数以实现这个目标。使用showlegend和height、width调整图形显示。

选择数据可视化工具

考虑使用Plotly的不同数据可视化工具,如Sankey图或Parcats图,来制作连接相同细胞类型的群组的alluvial图。

使用Plotly的桑基图创建图表

创建节点和链接

我正在构建桑基图,首先整理节点标签列表,然后确定每个标签的索引。接着定义源索引、目标索引和值,最后创建函数来生成alluvial plot。

将数据链接

正在将celltype_ratio中的每一行与组和细胞类型链接,使用相对频率作为值。比如,组为'Sample1',细胞类型为'Type1',相对频率为某个值。

指明节点和链接

列出了节点和链接之间的匹配关系,设计了Sankey图的标签和颜色。图表更新后的标题和字体大小已确定。

定义和调整颜色

我在定义节点颜色和链接颜色时,使用默认色和轻灰色来区分组节点和细胞类型节点,并且确保链接颜色与细胞类型的颜色相匹配。这将帮助实现预期效果。

创建节点和链接

我正在为所有节点创建列表,包括组和细胞类型。然后,我寻找并应用了组和细胞类型之间的连接,设置了颜色和权重。

답변

您希望修改代码,以在可视化中将相同的细胞类型在不同的组之间连接起来,类似于Alluvial图的效果。下面是修改后的代码,使用Plotly的Sankey图来实现这种效果:

import pandas as pd import plotly.graph_objs as go import os print("当前工作目录是:", os.getcwd()) # 示例数据 data = { 'group': ['Sample1', 'Sample1', 'Sample1', 'Sample2', 'Sample2', 'Sample2'], 'celltype': ['Type1', 'Type2', 'Type3', 'Type1', 'Type2', 'Type3'], 'n': [100, 200, 150, 120, 180, 130] } scedata = pd.DataFrame(data) # 计算相对频率 celltype_ratio = scedata.groupby(['group', 'celltype'])['n'].sum().reset_index() celltype_ratio['relative_freq'] = celltype_ratio.groupby('group')['n'].transform(lambda x: x / x.sum()) # 颜色调色板 mycolor = ['#efb306', '#7db954', '#852f88', '#4e54ac', '#0f8096'] # 模拟 Alluvial 图风格的调整 def create_alluvial_like_plot(df): # 创建节点列表 groups = df['group'].unique() celltypes = df['celltype'].unique() nodes = list(groups) + list(celltypes) label_to_index = {label: idx for idx, label in enumerate(nodes)} # 创建链接 sources = [] targets = [] values = [] colors = [] for idx, row in df.iterrows(): group = row['group'] celltype = row['celltype'] value = row['relative_freq'] source_idx = label_to_index[group] target_idx = label_to_index[celltype] sources.append(source_idx) targets.append(target_idx) values.append(value) # 获取细胞类型对应的颜色 celltype_idx = list(celltypes).tolist().index(celltype) colors.append(mycolor[celltype_idx % len(mycolor)]) # 设置节点颜色 node_colors = ['lightgray'] * len(groups) + [mycolor[i % len(mycolor)] for i in range(len(celltypes))] # 创建 Sankey 图 fig = go.Figure(data=[go.Sankey( node=dict( pad=15, thickness=20, line=dict(color="black", width=0.5), label=nodes, color=node_colors ), link=dict( source=sources, target=targets, value=values, color=colors ) )]) fig.update_layout( title_text="冲击桑基图(Alluvial风格)", font_size=10 ) return fig # 生成图表 alluvial_like = create_alluvial_like_plot(celltype_ratio) # 保存为HTML alluvial_like.write_html("alluvial_like_plot.html") print("图表已生成为 alluvial_like_plot.html")

此修改后的代码使用Plotly的Sankey图来模拟Alluvial图的效果,将相同的细胞类型在不同的组之间连接起来,实现了您在R代码中使用geom_flow的效果。

解释:

  • 节点创建: 我们将所有的组(group)和细胞类型(celltype)作为节点。
  • 链接创建: 根据每一行的数据,创建从组到细胞类型的链接,链接的宽度(value)为相对频率。
  • 颜色设置: 为每个细胞类型设置独特的颜色,组的节点颜色设置为灰色。
  • 图表绘制: 使用Plotly的go.Sankey绘制桑基图,并设置布局和样式。

效果:

生成的图表将显示不同的组(如Sample1和Sample2)与各个细胞类型之间的流动关系,链接的宽度代表相对频率,同一细胞类型在不同组之间的颜色一致,便于跟踪和比较。

이 Q&A 공유하기