如何使用数据框定义sankey图的结构?

问题描述 投票:7回答:1

这可能听起来像一个非常广泛的问题,但如果你让我描述一些细节,我可以向你保证这是非常具体的。以及令人沮丧,令人沮丧和愤怒的诱惑。


下图描述苏格兰选举,并基于plot.ly的代码:

情节1:

enter image description here

数据集1:

data = [['Source','Target','Value','Color','Node, Label','Link Color'],
        [0,5,20,'#F27420','Remain+No – 28','rgba(253, 227, 212, 0.5)'],
        [0,6,3,'#4994CE','Leave+No – 16','rgba(242, 116, 32, 1)'],
        [0,7,5,'#FABC13','Remain+Yes – 21','rgba(253, 227, 212, 0.5)'],
        [1,5,14,'#7FC241','Leave+Yes – 14','rgba(219, 233, 246, 0.5)'],
        [1,6,1,'#D3D3D3','Didn’t vote in at least one referendum – 21','rgba(73, 148, 206, 1)'],
        [1,7,1,'#8A5988','46 – No','rgba(219, 233, 246,0.5)'],
        [2,5,3,'#449E9E','39 – Yes','rgba(250, 188, 19, 1)'],
        [2,6,17,'#D3D3D3','14 – Don’t know / would not vote','rgba(250, 188, 19, 0.5)'],
        [2,7,2,'','','rgba(250, 188, 19, 0.5)'],
        [3,5,3,'','','rgba(127, 194, 65, 1)'],
        [3,6,9,'','','rgba(127, 194, 65, 0.5)'],
        [3,7,2,'','','rgba(127, 194, 65, 0.5)'],
        [4,5,5,'','','rgba(211, 211, 211, 0.5)'],
        [4,6,9,'','','rgba(211, 211, 211, 0.5)'],
        [4,7,8,'','','rgba(211, 211, 211, 0.5)']
        ]

情节如何建立:

我从各种来源中获取了一些关于sankey图表行为的重要细节,例如:

挑战:

正如您将在下面的详细信息中看到的那样,节点,标签和颜色不会以与源数据帧结构相同的顺序应用于图表。其中一些是完美的,因为你有各种元素描述相同的节点,如颜色,目标,值和链接颜色。一个节点'Remain+No – 28'看起来像这样:

enter image description here

数据集的附带部分如下所示:

[0,5,20,'#F27420','Remain+No – 28','rgba(253, 227, 212, 0.5)'],
[0,6,3,'#4994CE','Leave+No – 16','rgba(242, 116, 32, 1)'],
[0,7,5,'#FABC13','Remain+Yes – 21','rgba(253, 227, 212, 0.5)'],

所以这部分源代码描述了一个节点[0],其中有三个相应的目标[5, 6, 7]和三个具有值[20, 3, 5]的链接。 '#F27420'是节点的橙色(ish)颜色,颜色'rgba(253, 227, 212, 0.5)''rgba(242, 116, 32, 1)''rgba(253, 227, 212, 0.5)'描述从节点到某些目标的链接的颜色。到目前为止,上述示例中未使用的信息是:

数据样本2(部分)

[-,-,--'-------','---------------','-------------------'],
[-,-,-,'#4994CE','Leave+No – 16','-------------------'],
[-,-,-,'#FABC13','Remain+Yes – 21','-------------------'],

并且该信息用于引入图表的其余元素。

那么,问题是什么?在下面的进一步详细信息中,只要数据集中的新行数据插入新链接,并且如果尚未使用该信息对其他元素(颜色,标签)进行其他更改,您将看到一切都有意义。 。我将更具体地使用两个截图来自我使用左边的绘图和右边的代码创建的设置:

以下数据样本按照上面描述的逻辑生成下图:

数据样本3

data = [['Source','Target','Value','Color','Node, Label','Link Color'],
        [0,5,20,'#F27420','Remain+No – 28','rgba(253, 227, 212, 0.5)'],
        [0,6,3,'#4994CE','Leave+No – 16','rgba(242, 116, 32, 1)'],
        [0,7,5,'#FABC13','Remain+Yes – 21','rgba(253, 227, 212, 0.5)'],
        [1,5,14,'#7FC241','Leave+Yes – 14','rgba(219, 233, 246, 0.5)'],
        [1,6,1,'#D3D3D3','Didn’t vote in at least one referendum – 21','rgba(73, 148, 206, 1)']]

屏幕截图1 - 带有数据样本3的部分图

enter image description here

问题:

在数据集中添加行[1,7,1,'#8A5988','46 – No','rgba(219, 233, 246,0.5)']会在源[5]和目标[7]之间生成新链接,但会同时将颜色和标签应用于目标5。我认为应用于图表的下一个标签是'Remain+Yes – 21',因为它还没有被使用过。但这里发生的是标签'46 – No'适用于Target 5.为什么?

屏幕截图2 - 数据样本3 + [1,7,1,'#8A5988','46 – No','rgba(219, 233, 246,0.5)']的部分图:

enter image description here

您如何根据该数据帧辨别什么是源以及什么是目标?

我知道这个问题既奇怪又难以回答,但我希望有人有个建议。我也知道数据框可能不是sankey图表的最佳来源。也许是json呢?


完整的代码和数据示例,可轻松复制和粘贴Jupyter笔记本:


import pandas as pd
import numpy as np
import plotly.graph_objs as go
from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot
init_notebook_mode(connected=True)

# Original data
data = [['Source','Target','Value','Color','Node, Label','Link Color'],
    [0,5,20,'#F27420','Remain+No – 28','rgba(253, 227, 212, 0.5)'],
    [0,6,3,'#4994CE','Leave+No – 16','rgba(242, 116, 32, 1)'],
    [0,7,5,'#FABC13','Remain+Yes – 21','rgba(253, 227, 212, 0.5)'],
    [1,5,14,'#7FC241','Leave+Yes – 14','rgba(219, 233, 246, 0.5)'],
    [1,6,1,'#D3D3D3','Didn’t vote in at least one referendum – 21','rgba(73, 148, 206, 1)'],
    [1,7,1,'#8A5988','46 – No','rgba(219, 233, 246,0.5)'],
    [2,5,3,'#449E9E','39 – Yes','rgba(250, 188, 19, 1)'],
    [2,6,17,'#D3D3D3','14 – Don’t know / would not vote','rgba(250, 188, 19, 0.5)'],
    [2,7,2,'','','rgba(250, 188, 19, 0.5)'],
    [3,5,3,'','','rgba(127, 194, 65, 1)'],
    [3,6,9,'','','rgba(127, 194, 65, 0.5)'],
    [3,7,2,'','','rgba(127, 194, 65, 0.5)'],
    [4,5,5,'','','rgba(211, 211, 211, 0.5)'],
    [4,6,9,'','','rgba(211, 211, 211, 0.5)'],
    [4,7,8,'','','rgba(211, 211, 211, 0.5)']
    ]



headers = data.pop(0)
df = pd.DataFrame(data, columns = headers)
scottish_df = df

data_trace = dict(
    type='sankey',
    domain = dict(
      x =  [0,1],
      y =  [0,1]
    ),
    orientation = "h",
    valueformat = ".0f",
    node = dict(
      pad = 10,
      thickness = 30,
      line = dict(
        color = "black",
        width = 0
      ),
      label =  scottish_df['Node, Label'].dropna(axis=0, how='any'),
      color = scottish_df['Color']
    ),
    link = dict(
      source = scottish_df['Source'].dropna(axis=0, how='any'),
      target = scottish_df['Target'].dropna(axis=0, how='any'),
      value = scottish_df['Value'].dropna(axis=0, how='any'),
      color = scottish_df['Link Color'].dropna(axis=0, how='any'),
  )
)

layout =  dict(
    title = "Scottish Referendum Voters who now want Independence",
    height = 772,
    font = dict(
      size = 10
    ),    
)

fig = dict(data=[data_trace], layout=layout)
iplot(fig, validate=False)
python jupyter-notebook sankey-diagram plotly-python
1个回答
5
投票

这个问题看起来很奇怪,但只有在你分析如何创建plotly中的sankey图之前:

创建sankey图时,发送给它:

  1. 节点列表
  2. 链接列表

这些列表彼此限制。当您创建5长度节点列表时,任何边缘将在其开始和结束时了解0,1,2,3,4。在您的程序中,您错误地创建了节点 - 您创建了链接列表,然后通过它创建节点。看看你的图表。它有两个黑色节点,里面有undefined。你的数据集的长度是多少......是的,5。您的节点索引在4上结束,并且没有真正定义目标节点。您在数据集中添加第六个列表 - bingo! - 有nodes[5]存在!只需尝试在数据集中添加另一个新行:

[1,7,1,'#FF0000','WAKA','rgba(219, 233, 246,0.5)']

你会发现另一个黑色条纹是红色的。你有五个节点(因为你有5个链接,你通过迭代链接列表创建节点),但链接目标索引是5,6,7。您可以通过两种方式修复它:

  1. 将数据集中的Target更改为2,3,4
  2. 分别创建节点和链接(正确方式)

我希望我帮助你解决你的问题和情节创造的理解(更重要的是IMO)。

编辑:以下是单独节点/链接创建的示例(请注意,node中的data_trace部分仅使用nodes_df数据,link中的data_trace部分仅使用links_df数据,nodes_dflinks_df长度不相等):

import pandas as pd
import numpy as np
import plotly.graph_objs as go
from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot
init_notebook_mode(connected=True)

nodes = [
    ['ID', 'Label', 'Color'],
    [0,'Remain+No – 28','#F27420'],
    [1,'Leave+No – 16','#4994CE'],
    [2,'Remain+Yes – 21','#FABC13'],
    [3,'Leave+Yes – 14','#7FC241'],
    [4,'Didn’t vote in at least one referendum – 21','#D3D3D3'],
    [5,'46 – No','#8A5988']
]
links = [
    ['Source','Target','Value','Link Color'],
    [0,3,20,'rgba(253, 227, 212, 0.5)'],
    [0,4,3,'rgba(242, 116, 32, 1)'],
    [0,2,5,'rgba(253, 227, 212, 0.5)'],
    [1,5,14,'rgba(219, 233, 246, 0.5)'],
    [1,3,1,'rgba(73, 148, 206, 1)'],
    [1,4,1,'rgba(219, 233, 246,0.5)'],
    [1,2,10,'rgba(8, 233, 246,0.5)'],
    [1,3,5,'rgba(219, 77, 246,0.5)'],
    [1,5,12,'rgba(219, 4, 246,0.5)']
]

nodes_headers = nodes.pop(0)
nodes_df = pd.DataFrame(nodes, columns = nodes_headers)
links_headers = links.pop(0)
links_df = pd.DataFrame(links, columns = links_headers)

data_trace = dict(
    type='sankey',
    domain = dict(
      x =  [0,1],
      y =  [0,1]
    ),
    orientation = "h",
    valueformat = ".0f",
    node = dict(
      pad = 10,
      thickness = 30,
      line = dict(
        color = "black",
        width = 0
      ),
      label =  nodes_df['Label'].dropna(axis=0, how='any'),
      color = nodes_df['Color']
    ),
    link = dict(
      source = links_df['Source'].dropna(axis=0, how='any'),
      target = links_df['Target'].dropna(axis=0, how='any'),
      value = links_df['Value'].dropna(axis=0, how='any'),
      color = links_df['Link Color'].dropna(axis=0, how='any'),
  )
)

layout =  dict(
    title = "Scottish Referendum Voters who now want Independence",
    height = 772,
    font = dict(
      size = 10
    ),    
)

fig = dict(data=[data_trace], layout=layout)
iplot(fig, validate=False)

编辑2:让我们深入探讨:) sankey图中的节点和链接几乎完全独立。限制它们的唯一信息 - 链接中源 - 目标中的索引。所以我们可以为它们创建许多节点而没有链接(只需用它替换Edit1代码中的节点/链接):

nodes = [
    ['ID', 'Label', 'Color'],
    [0,'Remain+No – 28','#F27420'],
    [1,'Leave+No – 16','#4994CE'],
    [2,'Remain+Yes – 21','#FABC13'],
    [3,'Leave+Yes – 14','#7FC241'],
    [4,'Didn’t vote in at least one referendum – 21','#D3D3D3'],
    [5,'46 – No','#8A5988'],
    [6,'WAKA1','#8A5988'],
    [7,'WAKA2','#8A5988'],
    [8,'WAKA3','#8A5988'],
    [9,'WAKA4','#8A5988'],
    [10,'WAKA5','#8A5988'],
    [11,'WAKA6','#8A5988'],

]
links = [
    ['Source','Target','Value','Link Color'],
    [0,3,20,'rgba(253, 227, 212, 0.5)'],
    [0,4,3,'rgba(242, 116, 32, 1)'],
    [0,2,5,'rgba(253, 227, 212, 0.5)'],
    [1,5,14,'rgba(219, 233, 246, 0.5)'],
    [1,3,1,'rgba(73, 148, 206, 1)'],
    [1,4,1,'rgba(219, 233, 246,0.5)'],
    [1,2,10,'rgba(8, 233, 246,0.5)'],
    [1,3,5,'rgba(219, 77, 246,0.5)'],
    [1,5,12,'rgba(219, 4, 246,0.5)']
]

并且这些节点不会出现在图表中。

我们只能创建没有节点的链接:

nodes = [
    ['ID', 'Label', 'Color'],
]
links = [
    ['Source','Target','Value','Link Color'],
    [0,3,20,'rgba(253, 227, 212, 0.5)'],
    [0,4,3,'rgba(242, 116, 32, 1)'],
    [0,2,5,'rgba(253, 227, 212, 0.5)'],
    [1,5,14,'rgba(219, 233, 246, 0.5)'],
    [1,3,1,'rgba(73, 148, 206, 1)'],
    [1,4,1,'rgba(219, 233, 246,0.5)'],
    [1,2,10,'rgba(8, 233, 246,0.5)'],
    [1,3,5,'rgba(219, 77, 246,0.5)'],
    [1,5,12,'rgba(219, 4, 246,0.5)']
]

我们将只有从无处到无处的链接。

如果你想添加(1)带链接的新源,你应该在nodes中添加一个新列表,计算它的索引(这就是为什么我有ID列)并在links中添加一个新列表,其中Source等于节点索引。

如果你想为现有节点添加(2)一个新目标 - 只需在links中添加一个新列表并正确编写它的SourceTarget

    [1,100500,10,'rgba(219, 233, 246,0.5)'],
    [1,100501,10,'rgba(8, 233, 246,0.5)'],
    [1,100502,10,'rgba(219, 77, 246,0.5)'],
    [1,100503,10,'rgba(219, 4, 246,0.5)']

(这里我为4个新目标创建了4个新链接。来源是所有这些目标的索引为1的节点)。

(3 + 4):Sankey图表没有不同的来源和目标。所有这些都只是Sankey的节点。每个节点都可以是源节点和目标节点。看它:

nodes = [
    ['ID', 'Label', 'Color'],
    [0,'WAKA WANNA BE SOURCE','#F27420'],
    [1,'WAKA WANNA BE TARGET','#4994CE'],
    [2,'WAKA DON\'T KNOW WHO WANNA BE','#FABC13'],

]
links = [
    ['Source','Target','Value','Link Color'],
    [0,1,10,'rgba(253, 227, 212, 1)'],
    [0,2,10,'rgba(242, 116, 32, 1)'],
    [2,1,10,'rgba(253, 227, 212, 1)'],
]

在这里,您将获得3列Sankey图。 0节点是源,1是目标,2节点是1的源和2的目标。

© www.soinside.com 2019 - 2024. All rights reserved.