Plotly:如何绘制具有跨不同列的匹配行的 Sankey 图?
Plotly: How to plot Sankey diagram with matching rows across different columns?
我正在通过 plotly 绘制桑基图来比较不同类别的观察结果。但是,我对两个以上的分类有一些问题,其中每个分类中的观察顺序在每个节点的输入和输出之间发生变化。
我使用的代码如下:
def pl_sankey(df, label_color, categories, value, title='Sankey Diagram', fname=None, width=3000, height=1600, scale=2):
from IPython.display import Image
import plotly.graph_objects as go
import pandas as pd
df = df.copy()
labels = []
colors = []
# associate labels to colors
for k, v in label_color.items():
labels += [k]
colors += [v]
# transform df into a source-target pair
st_df = None
for i in range(len(categories)-1):
_st_df = df[[categories[i],categories[i+1],value]]
_st_df.columns = ['source', 'target', 'count']
st_df = pd.concat([st_df, _st_df])
st_df = st_df.groupby(['source', 'target']).agg({'count': 'sum'}).reset_index()
# add index for source-target pair
st_df['sourceID'] = st_df['source'].apply(lambda x: labels.index(str(x)))
st_df['targetID'] = st_df['target'].apply(lambda x: labels.index(str(x)))
# creating the sankey diagram
data = dict(
type='sankey', node=dict(
pad=15, thickness=20, line = dict(color='black', width=0.5), label=labels, color=colors,
),
link=dict(source=st_df['sourceID'], target=st_df['targetID'], value=st_df['count']),
)
layout = dict(title=title, font=dict(size=16, family='Arial'))
# creating figure
fig = go.Figure(dict(data=[data], layout=layout))
if fname:
fig.write_image(f'{fname}.pdf', format='pdf', width=width, height=height, scale=scale)
return Image(fig.to_image(format='png', width=width, height=height, scale=scale))
输入参数为:
- a pandas DataFrame
df
对每组行进行分组,例如:
# g1_l1 means group1, label1
g1 g2 g3 counts
0 g1_l1 g2_l1 g3_l1 10
1 g1_l3 g2_l2 g3_l1 1
2 g1_l1 g2_l2 g3_l2 1
3 g1_l2 g2_l2 g3_l1 40
4 g1_l2 g2_l3 g3_l2 20
5 g1_l3 g2_l1 g3_l2 10
label_color
是一个字典,其中键是标签,值是颜色
categories
是分组的列名,在本例中是['grouping1', 'grouping2', 'grouping3']
values
是counts的列名,本例为'counts'
一个执行示例如下:
df = pd.DataFrame([
['g1_l1', 'g2_l1', 'g3_l1', 10],
['g1_l3', 'g2_l2', 'g3_l1', 1],
['g1_l1', 'g2_l2', 'g3_l2', 1],
['g1_l2', 'g2_l2', 'g3_l1', 40],
['g1_l2', 'g2_l3', 'g3_l2', 20],
['g1_l3', 'g2_l1', 'g3_l2', 10],
], columns=['g1', 'g2', 'g3', 'counts'])
label_color = {
'g1_l1': '#1f77b4', 'g1_l2': '#ff7f0e', 'g1_l3': '#279e68',
'g2_l1': '#1f77b4', 'g2_l2': '#ff7f0e', 'g2_l3': '#279e68',
'g3_l1': '#1f77b4', 'g3_l2': '#ff7f0e',
}
pl_sankey(df, label_color, categories=df.columns[:-1], value='counts', title='', fname=None)
但是,此代码保证仅在两个相邻列之间进行行匹配。例如,考虑第 1 行:
g1 g2 g3 counts
1 g1_l3 g2_l2 g3_l1 1
这样的行应该从第一列的绿色簇 (g1_l3
) 开始,落在第二列的橙色簇 (g2_l2
) 并继续到蓝色簇 (g3_l1
)第三栏。但是,这在上一个图中没有得到尊重,其中第二列的输入与匹配输出的排序不同。
附上注释图以显示第二列观察值的跳跃(此类观察值在输入中倒数第二,但在第二列输出中最后):
我想按照一行的路径从第一列到最后一列。这可能吗?如何使用 Sankey 图实现?
我可能完全误解了这里的某些内容,但我希望能以正确的方式指导您。因此,如果我错了,请原谅我,但您似乎误解了 plotly sankey 图的一些内部工作原理。别担心,你是 .
你是说:
Such row should start from green cluster (g1_l3)
on first column, land
in orange cluster (g2_l2)
in second column and continue to blue
cluster (g3_l1)
on third column
因此,如果我理解正确的话,您希望这种特殊关系被说明为:
但这并不是一个 plotly sankey 图的工作方式。相反,从 g1_l3
到 g2_l2
的数量与进入 g2_l2
的其他数量组合在一起,然后作为聚合值“发送”到 g3_l1
。你有这条线的原因:
...是因为你也有关系 g2_l2 , g3_l1, 1
:
如果你以某种方式成功地说明了数据框中的关系完全你如何描述桑基图,它就不再是桑基图了。
很抱歉,我现在只能为您做这些了。
我正在通过 plotly 绘制桑基图来比较不同类别的观察结果。但是,我对两个以上的分类有一些问题,其中每个分类中的观察顺序在每个节点的输入和输出之间发生变化。
我使用的代码如下:
def pl_sankey(df, label_color, categories, value, title='Sankey Diagram', fname=None, width=3000, height=1600, scale=2):
from IPython.display import Image
import plotly.graph_objects as go
import pandas as pd
df = df.copy()
labels = []
colors = []
# associate labels to colors
for k, v in label_color.items():
labels += [k]
colors += [v]
# transform df into a source-target pair
st_df = None
for i in range(len(categories)-1):
_st_df = df[[categories[i],categories[i+1],value]]
_st_df.columns = ['source', 'target', 'count']
st_df = pd.concat([st_df, _st_df])
st_df = st_df.groupby(['source', 'target']).agg({'count': 'sum'}).reset_index()
# add index for source-target pair
st_df['sourceID'] = st_df['source'].apply(lambda x: labels.index(str(x)))
st_df['targetID'] = st_df['target'].apply(lambda x: labels.index(str(x)))
# creating the sankey diagram
data = dict(
type='sankey', node=dict(
pad=15, thickness=20, line = dict(color='black', width=0.5), label=labels, color=colors,
),
link=dict(source=st_df['sourceID'], target=st_df['targetID'], value=st_df['count']),
)
layout = dict(title=title, font=dict(size=16, family='Arial'))
# creating figure
fig = go.Figure(dict(data=[data], layout=layout))
if fname:
fig.write_image(f'{fname}.pdf', format='pdf', width=width, height=height, scale=scale)
return Image(fig.to_image(format='png', width=width, height=height, scale=scale))
输入参数为:
- a pandas DataFrame
df
对每组行进行分组,例如:
# g1_l1 means group1, label1
g1 g2 g3 counts
0 g1_l1 g2_l1 g3_l1 10
1 g1_l3 g2_l2 g3_l1 1
2 g1_l1 g2_l2 g3_l2 1
3 g1_l2 g2_l2 g3_l1 40
4 g1_l2 g2_l3 g3_l2 20
5 g1_l3 g2_l1 g3_l2 10
label_color
是一个字典,其中键是标签,值是颜色categories
是分组的列名,在本例中是['grouping1', 'grouping2', 'grouping3']
values
是counts的列名,本例为'counts'
一个执行示例如下:
df = pd.DataFrame([
['g1_l1', 'g2_l1', 'g3_l1', 10],
['g1_l3', 'g2_l2', 'g3_l1', 1],
['g1_l1', 'g2_l2', 'g3_l2', 1],
['g1_l2', 'g2_l2', 'g3_l1', 40],
['g1_l2', 'g2_l3', 'g3_l2', 20],
['g1_l3', 'g2_l1', 'g3_l2', 10],
], columns=['g1', 'g2', 'g3', 'counts'])
label_color = {
'g1_l1': '#1f77b4', 'g1_l2': '#ff7f0e', 'g1_l3': '#279e68',
'g2_l1': '#1f77b4', 'g2_l2': '#ff7f0e', 'g2_l3': '#279e68',
'g3_l1': '#1f77b4', 'g3_l2': '#ff7f0e',
}
pl_sankey(df, label_color, categories=df.columns[:-1], value='counts', title='', fname=None)
但是,此代码保证仅在两个相邻列之间进行行匹配。例如,考虑第 1 行:
g1 g2 g3 counts
1 g1_l3 g2_l2 g3_l1 1
这样的行应该从第一列的绿色簇 (g1_l3
) 开始,落在第二列的橙色簇 (g2_l2
) 并继续到蓝色簇 (g3_l1
)第三栏。但是,这在上一个图中没有得到尊重,其中第二列的输入与匹配输出的排序不同。
附上注释图以显示第二列观察值的跳跃(此类观察值在输入中倒数第二,但在第二列输出中最后):
我想按照一行的路径从第一列到最后一列。这可能吗?如何使用 Sankey 图实现?
我可能完全误解了这里的某些内容,但我希望能以正确的方式指导您。因此,如果我错了,请原谅我,但您似乎误解了 plotly sankey 图的一些内部工作原理。别担心,你是
你是说:
Such row should start from green cluster
(g1_l3)
on first column, land in orange cluster(g2_l2)
in second column and continue to blue cluster(g3_l1)
on third column
因此,如果我理解正确的话,您希望这种特殊关系被说明为:
但这并不是一个 plotly sankey 图的工作方式。相反,从 g1_l3
到 g2_l2
的数量与进入 g2_l2
的其他数量组合在一起,然后作为聚合值“发送”到 g3_l1
。你有这条线的原因:
...是因为你也有关系 g2_l2 , g3_l1, 1
:
如果你以某种方式成功地说明了数据框中的关系完全你如何描述桑基图,它就不再是桑基图了。
很抱歉,我现在只能为您做这些了。