Вторая легенда Боке, показывающая радиус рассеяния - PullRequest
0 голосов
/ 28 мая 2019

У меня есть график рассеяния Боке (bokeh==1.0.4) с использованием полярной проекции.Радиус точек соответствует RadiusSize в ColumnDataSource, а цвет соответствует DepthClass.

Я создал второй «фиктивный» график рассеяния, чтобы получить легенду, соответствующую fill_color (depth_legend).Я хотел бы вторую легенду, соответствующую радиусу.Данные RadiusSize представляют собой целые числа в диапазоне от 1 до 5. Я ищу вторую легенду, очень похожую на эту легенду matplotlib (см. Принятый ответ).

Вот мой соответствующий код построения:

def make_scatter(event_data):
  '''
  Create a polar scatter figure

  Parameters
  ----------
  event_data: Pandas dataframe

  Returns
  -------
  p: Bokeh Figure object
  '''

  cds = create_cds(event_data)

  p = figure(
      title="",
      name="scatter_fig",
      width=600, height=600,
      tools='',
  )

  # Project data into polar coordinates
  # customjs from bryevdv (https://github.com/bokeh/bokeh/issues/657)
  polarx = CustomJSTransform(args=dict(source=cds), v_func='''
  const new_xs = new Array(source.data.elev_project_vectors.length)
  for(var i = 0; i < new_xs.length; i++) {
      new_xs[i] = source.data.elev_project_vectors[i] * Math.sin(source.data.elev_angles[i] )
  }
  return new_xs
  ''')

  polary = CustomJSTransform(args=dict(source=cds), v_func='''
  const new_ys = new Array(source.data.elev_project_vectors.length)
  for(var i = 0; i < new_ys.length; i++) {
      new_ys[i] = source.data.elev_project_vectors[i] * Math.cos(source.data.elev_angles[i] )
  }
  return new_ys
  ''')

  event_scatter = p.scatter(
    x=transform('elev_project_vectors', polarx),
    y=transform('elev_project_vectors', polary),
    radius='RadiusSize',
    fill_color='DepthClass', fill_alpha=1.0,
    name='event_scatter',
    source=cds)

  # This is a dummy glyph just to have consistent colors for a custom legend
  event_scatter_dummy = p.scatter(
    x=[1,2,3],
    y=[1,2,3],
    radius=0,
    fill_color=['green','yellow','red'], fill_alpha=1.0,
    name='event_scatter_dummy',
    )

  depth_legend = Legend(items=[
    LegendItem(label='crown < 12"', renderers=[event_scatter_dummy], index=0),
    LegendItem(label='crown 12-44"', renderers=[event_scatter_dummy], index=1),
    LegendItem(label='crown > 44"', renderers=[event_scatter_dummy], index=2),
    ])
  p.add_layout(depth_legend)

  return p

Вот скриншот текущей фигуры Боке с единственной легендой, соответствующей fill_color: enter image description here В идеале, вторая легенда будет иметь метки (R1, R2,R3, R4, R5) и соответствующий диапазон увеличения радиуса окружности.Как я могу получить эту вторую легенду?

1 Ответ

0 голосов
/ 20 июня 2019

Я смог взломать это вместе, создав фиктивный невидимый круг, затем создав и собрав вместе пять отдельных Legend экземпляров, которые визуализируют фиктивный круг. Каждая легенда требует пользовательского позиционирования, используя location и label_standoff для правильного выравнивания. Затем я чередую циклические глифы и настраиваю их размер так, чтобы они соответствовали радиусу нанесенных данных.

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

Вот код Bokeh:

  event_radius_dummy_1 = p.circle(
    1,1,
    radius=0,
    fill_alpha=0.0, line_color='black', 
    name='event_radius_dummy_1'
    )

  event_legend1 = Legend(items=[
    LegendItem(label='R1', renderers=[event_radius_dummy_1])],
    location=(20,554), label_standoff=10, label_height=3)

  event_legend2 = Legend(items=[
    LegendItem(label='R2', renderers=[event_radius_dummy_1])],
    location=(14,532), label_standoff=5)

  event_legend3 = Legend(items=[
    LegendItem(label='R3', renderers=[event_radius_dummy_1])],
    location=(8,507), label_standoff=0)

  event_legend4 = Legend(items=[
    LegendItem(label='R4', renderers=[event_radius_dummy_1])],
    location=(2,479), label_standoff=-5)

  event_legend5 = Legend(items=[
    LegendItem(label='R5', renderers=[event_radius_dummy_1])],
    location=(-4,447), label_standoff=-10)

  event_legend_list = [event_legend1,event_legend2,event_legend3,event_legend4,event_legend5]
  for legend in event_legend_list:
    p.add_layout(legend)

  size_list = [15,26,37,48,59]
  index_list = [1,2,3,4,5]

  for index, size in zip(index_list, size_list):
    p.legend[index].glyph_height = size
    p.legend[index].glyph_width = size
    p.legend[index].padding = 0
    p.legend[index].margin = 0
    p.legend[index].border_line_alpha = 0
    p.legend[index].background_fill_alpha = 0

Результирующая цифра: enter image description here

...