Добавление меток на круговой / кольцевой диаграмме с использованием year_wedge в bokeh 2.x - PullRequest
0 голосов
/ 25 апреля 2020

У меня проблема с применением правильно выровненных наборов меток к диаграмме стиля пончика, созданной с помощью annual_wedge глифов в боке.

У меня проблемы с выравниванием меток, принадлежащих категориям "колец" диаграммы пончика " по горизонтали ", где по горизонтали - это выравнивание метки от inner_radius из annual_wedge до outer_radius. В настоящее время наборы меток, по-видимому, не имеют настройки inner_radius, соответствующей annual_wedge, что делает применение и выравнивание наборов меток к годовым клиньям чрезвычайно трудным.

Я следовал примеру в Добавление меток в p ie клин диаграммы в боке с использованием заполнения строк, но это кажется очень грязным хаком для перемещения меток по горизонтали.

Как я могу применить метки к годовому клину выровненным способом, соответствующим inner_radius годового глифа клина?

Вот мой пример кода:

# > gics_sector_data
gics_sector_data["gics_name"] = gics_sector_data["gics_name"].astype(str)
gics_sector_data["gics_name"] = gics_sector_data["gics_name"].str.pad(47, side = "left")

    # Sector Ring
    p.annular_wedge(x=9, y=9, inner_radius=0.8,outer_radius=2.5,
            start_angle=cumsum('angle', include_zero=True), end_angle=cumsum('angle'),
            line_color="white", fill_color='color', source=gics_sector_data)

    sourceSector = ColumnDataSource(gics_sector_data)
    labelsSector = LabelSet(x=9, y=9, text='gics_name',
                        angle=cumsum('angle', include_zero=True), source=sourceSector, render_mode='canvas',
                        text_font_size="8pt", text_align='left',background_fill_color='white')
    p.add_layout(labelsSector)

На изображении я установил цвет фона меток на белый, чтобы выровнять и разметить метки лучше видно.

example screenshot of bokeh annual_wedge labelset problem]

Только для вашей информации: это данные для отображения Глобальный отраслевой стандарт классификации

Ответы [ 2 ]

0 голосов
/ 25 апреля 2020

Благодаря Юджину я был на пути просветления и смог получить диаграмму, как я хотел. Мне пришлось изменить расчет положения меток путем вычисления середины между начальным углом и конечным углом сектора «пончика», потому что я хотел, чтобы метки были в середине каждого клина.

Я изменил пример Eugenes к этому, где «num» - это просто значение, которое я использую для вычисления относительной ширины каждого year_wedge (Eugene использует «value» в своем примере, я использую num для занятого числа слотов каждого клина в общей сложности) ширина слотов на «пончик», я надеюсь, это достаточно ясно):

R = 3
gics_sector_data= gics_sector_data.assign(
                end_angle=lambda d: np.cumsum(d['num'] / d['num'].sum() * 2 * pi),
                start_angle=lambda d: np.pad(d['end_angle'], (1, 0))[:-1],
                label_x=lambda d: R* 1.00 * np.cos(((d['end_angle']-d['start_angle'])/2)+d['start_angle']),
                label_y=lambda d: R* 1.00 * np.sin(((d['end_angle']-d['start_angle'])/2)+d['start_angle']),
                label_angle=lambda d: (((d['end_angle']-d['start_angle'])/2)+d['start_angle']))

Что-то о умножении 1,00, вы можете переместить метки от внешнего края клина, например, используя 0,95.

Что-то в стороне: я сократил имена меток, добавив столбец label_shortname, потому что bokeh не может выравнивать метки строк. Короткое имя будет использоваться для меток, длинное имя для всплывающей подсказки:

gics_sector_data['gics_name_short'] = gics_sector_data['gics_name'].str.slice(stop=20)

, а затем нарисует year_wedge, как с start_angles и end_anglescalculated:

# Sector Ring
p.annular_wedge(x=0, y=0, inner_radius=gics_sector_radius-ringWidth, outer_radius=gics_sector_radius,
                start_angle='start_angle', end_angle='end_angle',
                line_color="white", fill_color='color', source=gics_sector_data)

и, наконец, нарисует LabelSet с вычисленными метками label_x, label_y и label_angle, которые будут рисовать метку в середине клина, text_baseline = 'middle', обязателен для достижения хорошего результата:

sourceSector = ColumnDataSource(gics_sector_data)
labelsSector = LabelSet(x='label_x', y='label_y', text='gics_name_short',
                   angle='label_angle', source=sourceSector, render_mode='canvas',
                    text_font_size="7pt", text_align='right', text_baseline='middle')
p.add_layout(labelsSector)

и здесь идеальный результат 99,999% График результатов GICS bokeh , надеюсь, это поможет создать похожие диаграммы

0 голосов
/ 25 апреля 2020

Вам придется вычислять координаты самостоятельно.

Расширение на связанном примере:

from math import pi

import numpy as np
import pandas as pd

from bokeh.io import show
from bokeh.models import LabelSet, ColumnDataSource
from bokeh.palettes import Category20c
from bokeh.plotting import figure

x = {'United States': 157,
     'United Kingdom': 93,
     'Japan': 89,
     'China': 63,
     'Germany': 44,
     'India': 42,
     'Italy': 40,
     'Australia': 35,
     'Brazil': 32,
     'France': 31,
     'Taiwan': 31,
     'Spain': 29}

R = 0.4
data = (pd.Series(x)
        .reset_index(name='value')
        .rename(columns={'index': 'country'})
        .assign(end_angle=lambda d: np.cumsum(d['value'] / d['value'].sum() * 2 * pi),
                start_angle=lambda d: np.pad(d['end_angle'], (1, 0))[:-1],
                color=Category20c[len(x)],
                label_x=lambda d: R * 0.95 * np.cos(d['start_angle']),
                label_y=lambda d: R * 0.95 * np.sin(d['start_angle'])))

source = ColumnDataSource(data)

p_range = (-R * 1.2, R * 1.2)
p_size = 500
p = figure(plot_height=p_size, plot_width=p_size, toolbar_location=None,
           x_range=p_range, y_range=p_range,
           tools="hover", tooltips="@country: @value")
for r in [p.xaxis, p.yaxis, p.grid]:
    r.visible = False

p.wedge(x=0, y=0, radius=R,
        start_angle='start_angle', end_angle='end_angle',
        line_color="white", fill_color='color', legend_label='country', source=source)

p.add_layout(LabelSet(x='label_x', y='label_y', text='value', text_align='right',
                      angle='start_angle', source=source, render_mode='canvas'))

show(p)

enter image description here

...