在Bokeh中的饼图上添加自定义工具提示并正确显示

2024-04-28 21:53:42 发布

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

当我试图使用bokeh.charts.DonutHoverTool.tooltips中添加自定义值时,遇到了一些问题。在

我正在尝试在HoverTool.tooltips中添加百分比标记。我确信这是一个非常普遍的做法,在饼图中显示百分比值和绝对值,因为它增加了可读性。在

由于bokeh.charts.Donut是一个高级图表API,我似乎无法使自定义HoverTool.tooltips工作,如doc所示。在

from bokeh.plotting import output_notebook
from bokeh.charts import show,Donut
from bokeh.models import HoverTool
import pandas as pd
output_notebook()

d = {'posa': ['US','IT','FR','ES','DE','GB','CA','BE','AU','NL','NO','SE','DK'],
 'values': [4464, 989, 875, 824, 773, 733, 598, 307, 140, 132, 118, 112, 65]}
df = pd.DataFrame(d)
df['percentage'] = df['values']/df['values'].sum()

pie_chart = Donut(df,title='Distribution of unmatched by POSa',label='posa',values='values',plot_width=700,plot_height=700,)
hover = pie_chart.select(dict(type=HoverTool))
hover.tooltips = [('percentage', '@percentage'),('value','@values')]
show(pie_chart)

上面的代码生成了一个带有百分比的图:???在工具提示中。在

enter image description here

我想修复百分比标签,并显示正确。在

任何帮助都将不胜感激!在

谢谢。在


Tags: fromimportdfoutputchartbokeh百分比values
1条回答
网友
1楼 · 发布于 2024-04-28 21:53:42

我亲自动手,编写了一个类似于bokeh.charts中高级图表API的构建类。在

类别和功能:

from numpy import pi
from random import shuffle
from math import sin,cos
from bokeh.plotting import ColumnDataSource,output_notebook,figure
from bokeh.charts import show,Donut
from bokeh.models import HoverTool,Text
from bokeh import palettes
import pandas as pd

output_notebook()

class CustomPieBuilder:
    green ="#50ee70"
    red = "#ff7070"
    x_range = 1.1
    y_range = 1.1

    def __init__(self,df,label_name,column_name,tools='hover',tooltips=None,
                 reverse_color=False,colors=None,random_color_order=False,
                 plot_width=400,plot_height=400,title='Untitled',*args,**kwargs):
        p = self.setup_figure(tools,plot_width,plot_height,title)
        df = self.add_columns_for_pie_chart(df,column_name,colors,reverse_color,random_color_order)
        self.df = df
        self.plot_pie(p,df,label_name,*args,**kwargs)
        if tooltips:
            self.set_hover_tooltip(p,tooltips)

        self.add_text_label_on_pie(p,df,label_name)
        self.plot = p

    def setup_figure(self,tools,plot_width,plot_height,title):
        p = figure(
            x_range=(-self.x_range, self.x_range),
            y_range=(-self.y_range, self.y_range),
            tools=tools,
            plot_width=plot_width,
            plot_height=plot_height,
            title=title,
        )
        p.axis.visible = False
        p.xgrid.grid_line_color = None
        p.ygrid.grid_line_color = None
        return p

    @staticmethod
    def plot_pie(p,df,label_name,*args,**kwargs):
        for key, _df in df.groupby(label_name):
            source = ColumnDataSource(_df.to_dict(orient='list'))
            p.annular_wedge(
                x=0,
                y=0,
                inner_radius=0,
                outer_radius=1,
                start_angle='starts',
                end_angle='ends',
                color='colors',
                source=source,
                legend=key,
                *args,**kwargs)

    @staticmethod
    def set_hover_tooltip(p,tooltips):
        hover = p.select({'type':HoverTool})
        hover.tooltips = tooltips

    @staticmethod
    def add_columns_for_pie_chart(df,column_name,colors=None,reverse_color=False,random_color_order=False):
        r = 0.7
        df = df.copy()
        column_sum = df[column_name].sum()
        df['percentage'] = (df[column_name]/column_sum)
        percentages = [0]  + df['percentage'].cumsum().tolist()
        df['starts'] = [p * 2 * pi for p in percentages[:-1]]
        df['ends'] = [p * 2 * pi for p in percentages[1:]]

        df['middle'] = (df['starts'] + df['ends'])/2
        df['text_x'] = df['middle'].apply(cos)*r
        df['text_y'] =df['middle'].apply(sin)*r 
        df['text_angle'] = 0.0

        if colors:
            df['colors'] = colors
        else:
            if 'colors' not in df:
                reverse_color = -1 if reverse_color else 1
                colors = palettes.viridis(len(df))[::reverse_color]
                if random_color_order:
                    shuffle(colors)
                df['colors'] = colors
        return df

    @staticmethod
    def add_text_label_on_pie(p,df,label_name):
        source=ColumnDataSource(df.to_dict(orient='list'))
        txt = Text(x="text_x", y="text_y", text=label_name, angle="text_angle",
               text_align="center", text_baseline="middle",
               text_font_size='10pt',)
        p.add_glyph(source,txt)

def build_plot(df,label_name,column_name,tools='hover',tooltips=None,
                 reverse_color=False,colors=None,random_color_order=False,
                 plot_width=400,plot_height=400,title='Untitled',*args,**kwargs):

    customPie = CustomPieBuilder(df,label_name,column_name,tools,tooltips,
                 reverse_color,colors,random_color_order,
                 plot_width,plot_height,title,*args,**kwargs)

    return customPie.plot

代码:

^{pr2}$

图表: enter image description here

相关问题 更多 >