Sorting lost in Altair layered bar chart with error bars

Viewed 694

I am using a custom sort for my bar chart and it works well. However when I want to add error bars to it and use a layered chart then the sorting is not taking into account anymore. I also defined axis = None and that is also not taking into account.

Here is an example of the data:

df = pd.DataFrame(
    {'size' : ['huge', 'huge', 'huge', 'huge', 'huge', 'huge', 'big', 'big', 'big',  'big', 'big', 'big', 'small', 'small', 'small', 'small', 'small', 'small'],
     'weight': ['10 mg', '10 mg', '10 g', '10 g', '10 kg', '10 kg', '10 mg', '10 mg', '10 g', '10 g', '10 kg', '10 kg','10 mg', '10 mg', '10 g', '10 g', '10 kg', '10 kg'],
     'value': [3.5,2.6,5.1,6.5,2.3,4.6,7.1,2.8,6.9,1.5,2.6,2.8,6.9,2.3,4.6,3.5,2.6,5.1]
    }
)

Using just the bar chart works

alt.Chart(df).mark_bar().encode(
    x = alt.X('weight:O', title=None, axis=None, sort=['10 kg', '10 g', '10 mg']),
    y = alt.Y('mean(value)', title='Value'),
    color = alt.Color('weight:O', sort=['10 kg', '10 g', '10 mg']),
    column = alt.Column('size', sort=['huge', 'big', 'small'])
)

enter image description here

But not anymore with the error bars:

error_bars = alt.Chart().mark_errorbar(extent='ci').encode(
    x=alt.X('weight:O', sort=['10 kg', '10 g', '10 mg']),
    y='value:Q'
)

bars = alt.Chart().mark_bar().encode(
    x = alt.X('weight:O', title=None, axis=None, sort=['10 kg', '10 g', '10 mg']),
    y = alt.Y('mean(value)', title='Value'),
    color = alt.Color('weight:O', sort=['10 kg', '10 g', '10 mg'])
)

alt.layer(bars, error_bars, data=df).facet(
    column = alt.Column('size', sort=['huge', 'big', 'small'])
)

enter image description here

In both plots the axis and title have been set to None but is not taking into account in the layered chart. The weird thing is that the sorting is taking into account for the legend (see color = ...) but not for the x-axis (within each size).

Is there a way around this or am I not using the layered charts correctly?

1 Answers

To hide the axis in the layered chart, you should set axis=None and title=None in both layers:

error_bars = alt.Chart().mark_errorbar(extent='ci').encode(
    x=alt.X('weight:O',  title=None, axis=None, sort=['10 kg', '10 g', '10 mg']),
    y='value:Q'
)

bars = alt.Chart().mark_bar().encode(
    x = alt.X('weight:O', title=None, axis=None, sort=['10 kg', '10 g', '10 mg']),
    y = alt.Y('mean(value)', title='Value'),
    color = alt.Color('weight:O', sort=['10 kg', '10 g', '10 mg'])
)

alt.layer(bars, error_bars, data=df).facet(
    column = alt.Column('size', sort=['huge', 'big', 'small'])
)

enter image description here

You'll notice that my version of the chart has the correct sort order: this is because I'm using Altair version 4.0. There was a bug in earlier versions of Altair/Vega-Lite that prevented sort from behaving properly in layered charts.

Update to Altair 4.0 or newer and your sorting will work.

Related