Plotly Blank Sankey Diagram 没有错误

Plotly Blank Sankey Diagram with no errors

我正在尝试使用 plotly 绘制 Sankey 图,但得到空白输出,没有 python 或检查错误。

我创建的剧情class如下:

from typing import *
import logging
import pandas as pd
import plotly
import seaborn as sns

from .visualizer import AbstractVisualizer


class PlotlyVisualizer(AbstractVisualizer):
    logger = logging.getLogger('PlotlyVisualizer')

    def __init__(self, config: dict) -> None:
        """
        Plotly Visualizer
        """
        super().__init__(config=config)

    @staticmethod
    def __generate_sankey_figure__(nodes_df: pd.DataFrame, edges_df: pd.DataFrame, color_list: List,
                                   title: str = 'Sankey Diagram'):
        # creating the sankey diagram
        data = dict(
            type='sankey',
            node=dict(
                hoverinfo="all",
                pad=15,
                thickness=20,
                line=dict(
                    color="black",
                    width=0.5
                ),
                label=nodes_df['Node'],
                color=color_list
            ),
            link=dict(
                source=edges_df['Source'],
                target=edges_df['Target'],
                value=edges_df['Count']
            )
        )

        layout = dict(
            title=title,
            font=dict(
                size=10
            )
        )

        fig = dict(data=[data], layout=layout)
        return fig

    def plot(self, nodes_df: pd.DataFrame, edges_df: pd.DataFrame, attribute_cols: List, name_col: str):
        # Generate color palette
        color_palette = list(sns.color_palette(None, nodes_df.count()[0]).as_hex())
        color_list = color_palette
        fig = self.__generate_sankey_figure__(nodes_df=nodes_df, edges_df=edges_df, color_list=color_list,
                                              title=self.__config__['plot_name'])
        self.logger.info(fig)
        filename = "{}/{}.html".format(self.__config__['target_path'], self.__config__['plot_name'])

        plotly.offline.plot(fig, validate=True, filename=filename)

我用作输入的 nodes_df 和 edges_df 是这样的:

nodes_df:

                               Node  Count
0                New democracy_2019    158
1                New democracy_2007    153
2                       Syriza_2015    149
3                        Pasok_2007    102
4                       Syriza_2019     86
5                New democracy_2015     77
6          Movement for change_2019     22
7                          Kke_2007     22
8                  Golden dawn_2015     17
9                    The river_2015     17
10   Communist party of greece_2015     15
11   Communist party of greece_2019     15
12                      Syriza_2007     14
13          Independent greeks_2015     13
14  Pasok-democratic alignment_2015     13
15                        Laos_2007     10
16              Greek solution_2019     10
17                      Mera25_2019      9

edges_df:

                             Source                           Target  Count
0                New democracy_2015               New democracy_2019     28
1                New democracy_2007               New democracy_2015     22
2                       Syriza_2015                      Syriza_2019     18
3                New democracy_2007               New democracy_2019     16
4                        Pasok_2007  Pasok-democratic alignment_2015      6
5                        Pasok_2007         Movement for change_2019      4
6                          Kke_2007   Communist party of greece_2019      3
7    Communist party of greece_2015   Communist party of greece_2019      2
8                         Laos_2007               New democracy_2019      2
9                        Pasok_2007                      Syriza_2019      2
10  Pasok-democratic alignment_2015         Movement for change_2019      2
11                      Syriza_2015                      Mera25_2019      1
12                      Syriza_2007                      Syriza_2019      1
13                      Syriza_2007                      Syriza_2015      1
14                       Pasok_2007                      Syriza_2015      1
15               New democracy_2019               New democracy_2019      1
16                       Pasok_2007                      Mera25_2019      1
17               New democracy_2015               New democracy_2015      1
18               New democracy_2007               New democracy_2007      1
19               New democracy_2007          Independent greeks_2015      1
20                        Laos_2007               New democracy_2015      1
21                        Laos_2007              Greek solution_2019      1
22                   The river_2015               New democracy_2019      1

最终的图形字典结构如下:

{'data': 
  [
    {'type': 'sankey', 
      'node': 
      {'hoverinfo': 'all', 
        'pad': 15, 
        'thickness': 20, 
        'line': 
        {'color': 'black', 'width': 0.5}, 
        'label': 0                  New democracy_2019
                 1                  New democracy_2007
                 2                         Syriza_2015
                 3                          Pasok_2007
                 4                         Syriza_2019
                 5                  New democracy_2015
                 6            Movement for change_2019
                 7                            Kke_2007
                 8                    Golden dawn_2015
                 9                      The river_2015
                 10     Communist party of greece_2015
                 11     Communist party of greece_2019
                 12                        Syriza_2007
                 13            Independent greeks_2015
                 14    Pasok-democratic alignment_2015
                 15                          Laos_2007
                 16                Greek solution_2019
                 17                        Mera25_2019
                Name: Node, dtype: object, 
        'color': ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', '#9467bd', '#8c564b', '#e377c2', '#7f7f7f', '#bcbd22', '#17becf', '#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', '#9467bd', '#8c564b', '#e377c2', '#7f7f7f']}, 
        'link': 
        {'source':  0                  New democracy_2015
                    1                  New democracy_2007
                    2                         Syriza_2015
                    3                  New democracy_2007
                    4                          Pasok_2007
                    5                          Pasok_2007
                    6                            Kke_2007
                    7      Communist party of greece_2015
                    8                           Laos_2007
                    9                          Pasok_2007
                    10    Pasok-democratic alignment_2015
                    11                        Syriza_2015
                    12                        Syriza_2007
                    13                        Syriza_2007
                    14                         Pasok_2007
                    15                 New democracy_2019
                    16                         Pasok_2007
                    17                 New democracy_2015
                    18                 New democracy_2007
                    19                 New democracy_2007
                    20                          Laos_2007
                    21                          Laos_2007
                    22                     The river_2015
                    Name: Source, dtype: object, 
          'target': 0                  New democracy_2019
                    1                  New democracy_2015
                    2                         Syriza_2019
                    3                  New democracy_2019
                    4     Pasok-democratic alignment_2015
                    5            Movement for change_2019
                    6      Communist party of greece_2019
                    7      Communist party of greece_2019
                    8                  New democracy_2019
                    9                         Syriza_2019
                    10           Movement for change_2019
                    11                        Mera25_2019
                    12                        Syriza_2019
                    13                        Syriza_2015
                    14                        Syriza_2015
                    15                 New democracy_2019
                    16                        Mera25_2019
                    17                 New democracy_2015
                    18                 New democracy_2007
                    19            Independent greeks_2015
                    20                 New democracy_2015
                    21                Greek solution_2019
                    22                 New democracy_2019
                    Name: Target, dtype: object,
          'value':  0     28
                    1     22
                    2     18
                    3     16
                    4      6
                    5      4
                    6      3
                    7      2
                    8      2
                    9      2
                    10     2
                    11     1
                    12     1
                    13     1
                    14     1
                    15     1
                    16     1
                    17     1
                    18     1
                    19     1
                    20     1
                    21     1
                    22     1
                    Name: Count, dtype: int64}}], 
  'layout': 
    {'title': 'Sankey_2007_2015_2019', 
      'font': {'size': 10}}
    }

如开头所述,我没有收到 python 错误,也没有在浏览器上检查错误,只是呈现空白 html 文件。

提前致谢。

我找到了解决方案。问题是 edges_df 用 name/label 而不是索引来表示每个节点。

对生成数据的函数稍作修改 dict 就足够了:

    @staticmethod
    def __generate_sankey_figure__(nodes_df: pd.DataFrame, edges_df: pd.DataFrame, color_list: List,
                                   title: str = 'Sankey Diagram'):



        # Create the node indices
        nodes_list = nodes_df['Node'].tolist()
        edges_df['SourceID'] = edges_df['Source'].apply(lambda x: 
                                                        nodes_list.index(x))
        edges_df['TargetID'] = edges_df['Target'].apply(lambda x: 
                                                        nodes_list.index(x))
        # creating the sankey diagram
        data = dict(
            type='sankey',
            node=dict(
                hoverinfo="all",
                pad=15,
                thickness=20,
                    line=dict(
                    color="black",
                    width=0.5
                ),
                label=nodes_df['Node'],
                color=color_list
            ),
            link=dict(
                source=edges_df['SourceID'],
                target=edges_df['TargetID'],
                value=edges_df['Count']
            )
        )

        layout = dict(
            title=title,
            font=dict(
                size=10
            )
        )

        fig = dict(data=[data], layout=layout)
        return fig