我们如何在Sankey图表中设置数字格式,并在图表外设置标签?

2024-05-19 20:12:35 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一些简单的代码,可以生成一个漂亮的Sankey图表

import holoviews as hv
import plotly.graph_objects as go
import plotly.express as pex
hv.extension('bokeh')


sankey1 = hv.Sankey(df_final, kdims=['Sub_Market', 'Sport League'], vdims=["Revenue"])
hv.Sankey(sankey1)

sankey1.opts(cmap='Colorblind',label_position='right',
                                 edge_color='Sub_Market', edge_line_width=0,
                                 node_alpha=1.0, node_width=40, node_sort=True,
                                 width=800, height=600, bgcolor="snow",
                                 title="Flow of Revenue between Sub Market and Conference")

enter image description here

不幸的是,这些数字呈指数增长。我真的很想把它们以百万计展示出来。还有,有没有办法让右边的标签显示在右边,同时让左边的标签显示在左边,这样它们都在图表之外,更容易阅读

谢谢你的时间


Tags: 代码importnodeas图表标签plotlywidth
2条回答

下面的解决方案适用于holoviews,并且(可能)对plotly无效

holoviews中,您可以添加hv.Dimension(spec, **params),这使您有机会将带有关键字value_format的格式化程序应用于列名。此格式化程序可以预定义或定义。下面的示例演示如何通过自定义python函数定义简单的格式化程序

示例代码

import holoviews as hv
import pandas as pd

data = {'A':['XX','XY','YY','XY','XX','XX'],
        'B':['RR','KK','KK','RR','RK','KK'],
        'values':[1e6,5e5,8e4,15e3,19e2,1],
       }

df = pd.DataFrame(data)

def fmt(tick):
    if tick < 1e3:
        unit = ''
        num =  round(tick,2)
    elif tick < 1e6:
        unit = 'k'
        num =  round(tick/1e3,2)
    else:
        unit = 'm'
        num =  round(tick/1e6,2)
    return f'{num} {unit}'


hv.Sankey(df, vdims = hv.Dimension('values', value_format=fmt))

输出

Sanky with formatted values

首先,holoview允许为维度配置自定义格式

要按原样呈现数字,可以使用str函数作为维度的格式化程序

我使用了一个示例数据框来展示如何实现这一点。您可以在this runnable collab notebook中运行它

import holoviews as hv
from holoviews.core import Store
import pandas as pd

hv.ipython.notebook_extension('bokeh')

Store.set_current_backend('bokeh')
renderer = Store.renderers['bokeh']

df_final = pd.DataFrame({
    'Sub_Market': ['Central texas', 'Southern California', 'Florida'],
    'Sport League': ['MLS', 'NBA', 'MLS'],
    'Revenue': [1.4981211 * 10**5, 2.921212* 10**6, 1.2121112*10**6]
})

graph = hv.Sankey(
    df_final, 
    kdims=['Sub_Market', 'Sport League'],
    vdims=[hv.Dimension("Revenue", value_format=str)],
)

现在要自定义标签的位置,需要渲染的打印

这里我们使用bokeh作为后端,可以通过将图形对象作为参数转发给bokeh渲染器的get_plot方法来获得绘图

renderer = Store.renderers['bokeh']
plot = renderer.get_plot(graph)

现在,我们可以访问要自定义的绘图句柄。 应用于所有标签的默认x_offset值为0。 我们只需要在左侧标签上应用偏移

为此,我们增加了标签的数据源,以包含一个“x_offset”字段,并为我们希望定位在四边形左侧的标签设置偏移量

此外,我们需要设置plot.xrange的起始点,这样绘图就不会被截断

offset = -200
num_nodes = len(plot.handles['text_1_source'].data['x'])
plot.handles['text_1_source'].data['x_offset'] = [0]* num_nodes
num_left_nodes = 3
left_nodes_selection = slice(0, num_left_nodes)
plot.handles['text_1_source'].data['x_offset'][left_nodes_selection] = [offset]* num_left_nodes
plot.handles['text_1_glyph'].x_offset = {'field': 'x_offset' }
plot.handles['plot'].x_range.start += (2*offset)

最后,我们可以将绘图渲染为SVG组件,并将其显示在笔记本中

hv.ipython.notebook_extension('bokeh')
data, metadata = hv.ipython.display_hooks.render(plot, fmt='svg')
hv.ipython.display(hv.ipython.HTML(data["text/html"]))

sankey plot with customised label positions

相关问题 更多 >