Python 控制Sankey图连接

Python 控制Sankey图连接,python,matplotlib,sankey-diagram,Python,Matplotlib,Sankey Diagram,我试图使用Matplotlib Sankey图控制哪些流彼此连接。我正在修改基本的两个系统示例 我认为我的困惑归结为误解了这实际上意味着什么: 请注意,只指定了一个连接,但系统形成了一个回路,因为:(1)路径的长度是对齐的,(2)流的方向和顺序是镜像的 我制作了一个玩具示例,它使用单个数据集,然后为第二个系统修改它,以确保所有数字都匹配 import numpy as np import matplotlib.pyplot as plt from matplotlib.sankey impor

我试图使用Matplotlib Sankey图控制哪些流彼此连接。我正在修改基本的两个系统示例

我认为我的困惑归结为误解了这实际上意味着什么:

请注意,只指定了一个连接,但系统形成了一个回路,因为:(1)路径的长度是对齐的,(2)流的方向和顺序是镜像的

我制作了一个玩具示例,它使用单个数据集,然后为第二个系统修改它,以确保所有数字都匹配

import numpy as np
import matplotlib.pyplot as plt

from matplotlib.sankey import Sankey

plt.rcParams["figure.figsize"] = (15,10)


system_1 = [
    {"label": "1st",  "value":  2.00, "orientation":  0},
    {"label": "2nd",  "value":  0.15, "orientation": -1},
    {"label": "3rd",  "value":  0.60, "orientation": -1},
    {"label": "4th",  "value": -0.10, "orientation": -1},
    {"label": "5th",  "value":  0.25, "orientation": -1},
    {"label": "6th",  "value":  0.25, "orientation": -1},
    {"label": "7th",  "value":  0.25, "orientation": -1},
    {"label": "8th",  "value":  0.25, "orientation": -1},
    {"label": "9th",  "value":  0.25, "orientation": -1}
]

system_2 = system_1[:4]
system_2.append({"label": "new",  "value":  -0.25, "orientation": 1})


fig = plt.figure()
ax = fig.add_subplot(1, 1, 1, xticks=[], yticks=[], title="Where are all my cows?")
flows  = [x["value"] for x in system_1]
labels = [x["label"] for x in system_1]
orientations=[x["orientation"] for x in system_1]
sankey = Sankey(ax=ax, unit="cow")
sankey.add(flows=flows, 
           labels=labels,
           label='one',
           orientations=orientations)

sankey.add(flows=[-x["value"] for x in system_2], 
           labels=[x["label"] for x in system_2],
           label='two',
           orientations=[-x["orientation"] for x in system_2], 
           prior=0, 
           connect= (0,0)
          )

diagrams = sankey.finish()
diagrams[-1].patch.set_hatch('/')
plt.legend(loc='best')


plt.show()
这给了我:

它应该用匹配的标签连接流


我已经读过了,但它们并没有帮助我理解实际发生的事情。

让我们从解决困惑开始吧

我认为我的困惑归结为误解了这实际上意味着什么:

请注意,只指定了一个连接,但系统形成一个 电路,因为:(1)路径的长度是正确的,(2) 流的方向和顺序是镜像的

(2) 流的方向和顺序是镜像的

您可能理解错误的是镜像的含义,在本例中,这确实令人困惑。有人会想,镜像等于反转,但这只是部分正确:
(或者您在代码中称之为:
)必须反转,这一个是正确的。因为
对应于输入(
值>0
)或输出(
值<0
)。只有输出可以连接到输入,反之亦然

但是对于您尝试连接的两个流,
方向必须相同。这一个不是倒置的,但它仍然需要“镜像”。这是什么意思?好的,如果一个I/O正朝着他来自的箭头的方向看,它需要看到另一个I/O(就像在镜子中看一样),只有这样它们才能连接自己。作为一个非母语人士,解释起来并不容易,但我将尝试说明这一点:

Able to connect:         Not able to connect:        Not able to connect:
I/O  Mirror  I/O         I/O  Mirror  I/O            I/O  Mirror  I/O
╚══>   |    >══╝          ╗     |      ╔                    |      ║
                          ║     |      ║             ══>    |      ║
                          v     |      ^                    |      ^
在代码中,您已经反转了
方向
。这就是为什么橙色系统的第三个流位于左上角,而蓝色系统的对应流位于右下角。这些I/O不可能“看到”彼此

您可以通过删除
-
来恢复第二个系统的反转,该
-
x
置于以下方向:

orientations=[x["orientation"] for x in system_2]
您将看到,现在这些流彼此非常接近,但您所处的情况如
无法连接图(第2号)所示。这意味着图表的结构将无法以这种方式工作。您只能在以下三个方向上弯曲单流:-90°、0°或90°。哪些对应于
方向=-1、0或1
。直接连接这些流的唯一方法是设置它们的
方向=0
,但在我看来,这并不是您的目标

你需要一种新的方法来完成任务,这样你就不会陷入以前那种无法连接流的情况。我已经修改了你的代码(也许?)以达到你的目标。它看起来已经不一样了,但我认为这是一个很好的开始,可以了解方向、镜像等概念

(1) 路径的长度是对的

您将在下面的代码中看到,我为
pathLength
变量(在第二个系统中)设置了值。我已经说过,如果有太多的流需要连接,matplotlib就不能再自动连接了

编码和输出

import numpy as np
import matplotlib.pyplot as plt

from matplotlib.sankey import Sankey

plt.rcParams["figure.figsize"] = (15,10)


system_1 = [
    {"label": "1st",  "value": -2.00, "orientation":  1},
    {"label": "4th",  "value":  0.10, "orientation":  1},
    {"label": "2nd",  "value":  0.15, "orientation":  1},
    {"label": "3rd",  "value":  0.60, "orientation":  1},
    {"label": "5th",  "value":  0.25, "orientation": -1},
    {"label": "6th",  "value":  0.25, "orientation": -1},
    {"label": "7th",  "value":  0.25, "orientation":  1},
    {"label": "8th",  "value":  0.25, "orientation":  1},
    {"label": "9th",  "value":  0.25, "orientation":  0}
]

system_2 = [
    {"label": "1st",  "value":  2.00, "orientation":  1},
    {"label": "4th",  "value": -0.10, "orientation":  1},
    {"label": "2nd",  "value": -0.15, "orientation":  1},
    {"label": "3rd",  "value": -0.60, "orientation":  1},
    {"label": "new",  "value": -0.25, "orientation":  1}
]

fig = plt.figure()
ax = fig.add_subplot(1, 1, 1, xticks=[], yticks=[], title="Where are all my cows?")

flows_1  = [x["value"] for x in system_1]
labels_1 = [x["label"] for x in system_1]
orientations_1=[x["orientation"] for x in system_1]

flows_2  = [x["value"] for x in system_2]
labels_2 = [x["label"] for x in system_2]
orientations_2=[x["orientation"] for x in system_2]

sankey = Sankey(ax=ax, unit=None)
sankey.add(flows=flows_1, 
           labels=labels_1,
           label='one',
           orientations=orientations_1)

sankey.add(flows=flows_2, 
           labels=labels_2,
           label='two',
           orientations=orientations_2,
           pathlengths=[0, 0.4, 0.5, 0.65, 1.25],
           prior=0,
           connect=(0,0))

diagrams = sankey.finish()
diagrams[-1].patch.set_hatch('|')
diagrams[-0].patch.set_hatch('-')
plt.legend(loc='best')


plt.show()

我想最终理解这一点的过程不是创建一个非常复杂的示例并尝试使其看起来正确,而是从一个基本电路开始,尝试更改参数以查看其效果。还有一些可能有用的方法。