【问题标题】:Matplotlib Sankey labels and valuesMatplotlib Sankey 标签和值
【发布时间】:2020-05-04 03:14:33
【问题描述】:

我正在处理桑基图,但在标注过程中遇到了一些问题。有没有办法将每个流的标签和值放在同一行?我希望它们看起来像这样:“标签:值”。

这里是代码和结果图。

from matplotlib import pyplot as plt
from matplotlib.sankey import Sankey

fig = plt.figure(figsize=(8.3, 11.7))
ax = fig.add_subplot(1, 1, 1)
plt.axis('off')

# these will be provided soon
# Input = ...
# L0 = ...
# L1, L2, L3, L4, L5, L6, L7, L8, L9 = ...
# F9 = ...

sankey = Sankey(ax=ax,
                scale=1 / Input,
                offset=0.6,
                head_angle=135,
                shoulder=0,
                gap=0.2,
                radius=0.1,
                format='%.1f',
                unit='%')
s0 = sankey.add(flows=[Input, -L0, -(Input - L0)],
                labels=['Input 1', 'Loss 0', ''],
                orientations=[0, 1, 0],
                trunklength=1,
                rotation=-90,
                fc='crimson', alpha=0.8)
s1 = sankey.add(flows=[Input - L0, -L1, -L2, -L3, -L4, -L5, -L6, -L7, -L8, -L9, -F9],
                labels=['Input 2', 'Loss 1', 'Loss 2', 'Loss 3', 'Loss 4', 'Loss 5', 'Loss 6', 'Loss 7', 'Loss 8',
                        'Loss 9', 'Output'],
                orientations=[0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
                trunklength=1,
                rotation=-90,
                prior=0, connect=(2, 0),
                fc='crimson', alpha=0.6)
diagrams = sankey.finish()
for d in diagrams:
    for t in d.texts:
        t.set_fontsize(10)
        t.set_horizontalalignment('center')
        t.set_verticalalignment('center')

diagrams[0].texts[0].set_position(xy=[0, 0.4])
diagrams[0].texts[2].set_position(xy=[10, 10])

plt.show()

桑基图

【问题讨论】:

  • 请添加您正在使用的确切库的导入,并为Input, colors_2, F9, L0, L1, ...提供一些有意义的值

标签: python matplotlib label sankey-diagram


【解决方案1】:

假设您的输入值是显示的百分比,您可以通过手动将该信息添加到每个标签来达到您的目标。需要换行时使用'\n',在一行上写百分比时使用破折号' – ' 或冒号。您需要重置 sankey 的 formatunit 参数,以防止再次添加百分比。

由于sankey仍在编写空格式和单位,因此可以更新文本以删除空行并获得正确的垂直居中。

from matplotlib import pyplot as plt
from matplotlib.sankey import Sankey
from random import randint

Input = 240.1
L0 = 140.1
F9 = 21.1
L = [randint(1,300) for _ in range(9)]
norm_factor = (Input - L0 - F9) / sum(L)

flows_s2 = [Input - L0] + [-l * norm_factor for l in L] + [-F9]
labels_s2 = ['Input 2', 'Loss 1', 'Loss 2', 'Loss 3', 'Loss 4', 'Loss 5', 'Loss 6', 'Loss 7', 'Loss 8', 'Loss 9',
             'Output']
labels_s2_long = [f'{label}\n{flow} %' for label, flow in zip(labels_s2[:1], flows_s2)]
labels_s2_long += [f'{label} – {-flow:.1f} %' for label, flow in zip(labels_s2[1:], flows_s2[1:])]

fig = plt.figure(figsize=(8.3, 11.7))
ax = fig.add_subplot(1, 1, 1)
plt.axis('off')
sankey = Sankey(ax=ax,
                scale=2 / Input,
                offset=0.6,
                head_angle=135,
                shoulder=0,
                gap=0.2,
                radius=0.1,
                format='%.1f',
                unit='%')
s0 = sankey.add(flows=[Input, -L0, -(Input - L0)],
                labels=['Input 1', 'Loss 0', ''],
                orientations=[0, 1, 0],
                trunklength=1,
                rotation=-90,
                fc='crimson', alpha=0.8)
sankey.format = ''
sankey.unit = ''
s1 = sankey.add(flows=flows_s2,
                labels=labels_s2_long,
                orientations=[0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
                trunklength=1,
                rotation=-90,
                prior=0, connect=(2, 0),
                fc='tomato', alpha=0.6)
diagrams = sankey.finish()
for d in diagrams:
    for t in d.texts:
        text = t.get_text()
        if text[-1] == '\n': # remove empty line at the end, needed for centering
            t.set_text(text[:-1])
        t.set_fontsize(10)
        t.set_verticalalignment('center')
        if text[:4] == 'Loss' and text[:6] != 'Loss 0': # align all loss labels except loss 0
            t.set_horizontalalignment('left')
            xy = t.get_position()
            t.set_position(xy=(0.18, xy[1]))
        else:
            t.set_horizontalalignment('center')
        #t.set_bbox(dict(facecolor='red', alpha=0.5, edgecolor='blue'))

diagrams[0].texts[0].set_position(xy=(0, 0.42)) # adjust position of input 1
diagrams[0].texts[1].set_position(xy=(1.75, diagrams[0].texts[1].get_position()[1])) # adjust pos. of loss 0
diagrams[0].texts[2].set_text('')  # remove output 1 as it coincides with input 2
diagrams[1].texts[-1].set_position(xy=(diagrams[1].texts[-1].get_position()[0], -5)) # adjust pos. of output


plt.tight_layout()
plt.show()

【讨论】:

  • 嗨!非常感谢!这正是我想要的!
  • 我刚刚添加了一些代码来纠正“损失”线的垂直居中。
  • 嗨@JohanC,我刚刚发现,如果你设置unit=None,sankey 不会绘制任何值。像这样,标签会自动获得垂直更好的位置。不幸的是,在水平方向上它仍然是“中心”。
猜你喜欢
  • 1970-01-01
  • 2022-10-17
  • 1970-01-01
  • 2021-01-11
  • 2021-10-24
  • 2021-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多