散景饼图显示百分比标签倒置

时间:2021-05-19 15:20:53

标签: python pandas bokeh

我有一个按类别分组的数据框,我想生成一个包含每个类别百分比的饼图。我在 Python 中使用 Bokeh 库。

我的问题是饼图中的某些百分比标签显示不正确,如下图所示。 enter image description here

这是我用来生成饼图的代码:

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)

复制上面饼图的一些数据(制表符分隔)

category    paymentAmount
Chemicals   52800.95001766206
Research    110878.70999269483
Construction    266189.2100121978

任何想法如何解决这个问题?

先谢谢你!

1 个答案:

答案 0 :(得分:3)

我找到了两个有用的 StackOverflow 帖子来解决这个问题:

因此,我将您的代码修改如下:

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)

生成的饼图为:

enter image description here