Eilon Baer
Eilon Baer

Reputation: 85

Altair Bar Chart - label placement and formating

Following up on this question I have two additional options to implement:

  1. Set placement of label to be in middle of chart, regardless of bar height
  2. Format label to appear as part of string including parenthesis

My code currently looks like this:

df = pd.DataFrame({'name':['bar','foo'],
                  'presented_value':[2,20],
                  'coloring_value':[1,25]})

base = (alt.Chart(df, height=250, width=375).mark_bar()
 .encode(
    x='name',
    y=alt.Y('presented_value', axis=alt.Axis(orient='right')),
    color='name'
  )
)
bars = base.mark_bar().encode(color=alt.condition(
      alt.datum.presented_value > alt.datum.coloring_value,
      alt.value('lightgreen'),
      alt.value('darkred')
    ))

text_sub_brand = base.mark_text(
    align='center', baseline='bottom', 
    dy=35, fontSize=24
).encode(
    text='presented_value'
)
text_cluster = base.mark_text(
    align='center', baseline='bottom', 
    dy=50, fontSize=16
).encode(
    text='coloring_value'
).transform_calculate(label='"Cluster value: " + datum.coloring_value')


(bars + text_sub_brand + text_cluster).properties(width=700)

enter image description here

Regarding the placement I tried different parameters of the MarkDef using the docs here but didn't find an option that allows placement relative to chart and not to bar. As seen in the image above for foo bar I would like to avoid cases where the label is presented outside the Y axis area.

Regarding the formatting I tried implementing the solution here but for some reason didn't work in my case. Ideally I would like the format to be label='"(" + datum.coloring_value + ")"') but using parenthesis caused a JavaScript error:

This usually means there's a typo in your chart specification. See the javascript console for the full traceback.

Can this be done? Thanks!

Upvotes: 3

Views: 3756

Answers (1)

jakevdp
jakevdp

Reputation: 86310

Your text has a y encoding set to presented_value, so it will appear on the chart according to this. If you want it to be at a constant location on the chart, you can set the y encoding to alt.value(pixels_from_top).

For the formatting, you can use a calculate transform and then refer to this calculated value in the text encoding.

Put together, it looks like this:

import altair as alt
import pandas as pd

df = pd.DataFrame({'name':['bar','foo'],
                  'presented_value':[2,20],
                  'coloring_value':[1,25]})

base = (alt.Chart(df, height=250, width=375).mark_bar()
 .encode(
    x='name',
    y=alt.Y('presented_value', axis=alt.Axis(orient='right')),
    color='name'
  )
)
bars = base.mark_bar().encode(color=alt.condition(
      alt.datum.presented_value > alt.datum.coloring_value,
      alt.value('lightgreen'),
      alt.value('darkred')
    ))

text_sub_brand = base.mark_text(
    align='center', baseline='bottom', 
    dy=35, fontSize=24
).encode(
    y=alt.value(100),
    text='presented_value'
)
text_cluster = base.mark_text(
    align='center', baseline='bottom', 
    dy=50, fontSize=16
).encode(
    y=alt.value(100),
    text='label:N'
).transform_calculate(label='"(" + datum.coloring_value + ")"')


(bars + text_sub_brand + text_cluster).properties(width=700)

enter image description here

Upvotes: 6

Related Questions