简体   繁体   中英

Bokeh pie chart show percentage labels upside down

I have a dataframe with amounts grouped by categories and I want to generate a pie chart containing the percentages per category. I am using the Bokeh library in Python.

My problem is that some percetange labels are not displayed properly in the pie chart as shown in the following image. 在此处输入图像描述

Here is the code that I use to produce the pie chart:

df['angle'] = df['paymentAmount'] / df['paymentAmount'].sum() * 2 * pi
if len(df.index) > 2:
    df["color"] = GnBu[len(df.index)]
elif len(df.index) == 2:
    df["color"] = ["steelblue", "skyblue"]
else:
    df["color"] = ["steelblue"]
df["percentage"] = df["paymentAmount"] / df["paymentAmount"].sum()
df['percentage'] = df['percentage'].astype(float).map(lambda n: '{:.2%}'.format(n))
df["percentage"] = df['percentage'].astype(str)
df["percentage"] = df["percentage"].str.pad(35, side="left")
source = ColumnDataSource(df)
p = figure(width=figsize[0], height=figsize[1], toolbar_location=None,
           tooltips=[("percentage", "@percentage")],
           tools="hover", x_range=(-0.5, 1.0))
pie_chart = p.wedge(x=0, y=1, radius=0.4,
                    start_angle=cumsum('angle', include_zero=True), end_angle=cumsum('angle'),
                    line_color="white", fill_color='color', source=source)
labels = LabelSet(x=0, y=1, text='percentage', angle=cumsum('angle', include_zero=True), source=source,
                  render_mode='canvas')
p.add_layout(labels)

legend = Legend(items=[LegendItem(label=dict(field='category'), renderers=[pie_chart])],
                location=(0, figsize[1] - 100))
p.add_layout(legend, 'right')

p.axis.axis_label = None
p.axis.visible = False
p.grid.grid_line_color = None
save(p)

Some data to reproduce the the pie chart above (tab separated)

category    paymentAmount
Chemicals   52800.95001766206
Research    110878.70999269483
Construction    266189.2100121978

Any ideas how to solve this?

Thank you in advance!

I have found two useful StackOverflow posts to solve this:

Therefore, I have modified your code as follows:

df['angle'] = df['paymentAmount'] / df['paymentAmount'].sum() * 2 * pi
value = list(df["paymentAmount"])
df["cumulative_angle"] = [(sum(value[0:i + 1]) - (item / 2)) / sum(value) * 2 * pi for i, item in enumerate(value)]
df['cos'] = np.cos(df['cumulative_angle']) * 0.3
df['sin'] = np.sin(df['cumulative_angle']) * 0.3
if len(df.index) > 2:
    df["color"] = GnBu[len(df.index)]
elif len(df.index) == 2:
    df["color"] = ["steelblue", "skyblue"]
else:
    df["color"] = ["steelblue"]
df["percentage"] = df["paymentAmount"] / df["paymentAmount"].sum()
df['percentage'] = df['percentage'].astype(float).map(lambda n: '{:.2%}'.format(n))
df["percentage"] = df['percentage'].astype(str)
df["percentage"] = df["percentage"].str.pad(35, side="left")
source = ColumnDataSource(df)
p = figure(width=figsize[0], height=figsize[1], toolbar_location=None, x_range=(-1.0, 1.0), y_range=(-1.0, 1.0),
           tooltips=[("percentage", "@percentage")], tools="hover")
pie_chart = p.wedge(x=0, y=0, radius=0.5,
                    start_angle=cumsum('angle', include_zero=True), end_angle=cumsum('angle'),
                    line_color="white", fill_color='color', source=source)
labels = LabelSet(x="cos", y="sin", y_offset=0, text='percentage', text_align="center", angle=0, source=source,
                  render_mode='canvas')
p.add_layout(labels)

legend = Legend(items=[LegendItem(label=dict(field="category"), renderers=[pie_chart])],
                location=(0, figsize[1] - 100))
p.add_layout(legend, 'right')

p.axis.axis_label = None
p.axis.visible = False
p.grid.grid_line_color = None
save(p)

The produced pie chart is:

在此处输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM