Search code examples
pythonpandasplotaltair

Altair: add a line in a grouped bar chart


I have this data that I want to plot. In column 'IPVA' there are [0, 1, 2] as possible values, where 1 and 0 are the data that I want to plot as a grouped bar chart, and the 2 is data that I want to plot as a line above them. Right now I'm using the next code to create both graphics, but when I try to concat them, I get this error, and I don't know how to proceed:

enter image description here

base = alt.Chart(dataset_obj1).encode(x=alt.X('Periodo:N'))

bar = base.mark_bar(color='#2A629A').encode(
    x=alt.X('IPVA:O', axis=None).title('Periodo'),
    y=alt.Y('Total:Q', scale=alt.Scale(domain=[0, 0.38]), axis=alt.AxisConfig(titleColor='#2A629A')).title('IPVA nacional'),
    color='IPVA:N',
    column=alt.Column('Periodo:N', header=alt.Header(orient='bottom'))
).properties(
    width=50,
    height=300,
    title='IPVA en relación al salario medio'
).transform_filter(
    alt.FieldOneOfPredicate(field='IPVA', oneOf=[1, 0])
);

line = base.mark_line(color='red', point=True).encode(
    x=alt.X('Periodo:O'),
    y=alt.Y('Total:Q', scale=alt.Scale(domain=[0, 0.45]), axis=alt.AxisConfig(titleColor='red')).title('Salario medio nacional'),
    color=alt.value('red')
).properties(
    width=500,
    height=300,
).transform_filter(
    alt.FieldEqualPredicate(field='IPVA', equal=2)
);


(line + bar).resolve_scale(y='independent')

enter image description here

enter image description here

[........]
---> 28 (line + bar).resolve_scale(y='independent')

File ~\anaconda3\envs\mt_python\Lib\site-packages\altair\vegalite\v5\api.py:1240, in TopLevelMixin.__add__(self, other)
   1238 if not isinstance(other, TopLevelMixin):
   1239     raise ValueError("Only Chart objects can be layered.")
-> 1240 return layer(self, other)

File ~\anaconda3\envs\mt_python\Lib\site-packages\altair\vegalite\v5\api.py:3087, in _check_if_can_be_layered(spec)
   3085     for channel in ["row", "column", "facet"]:
   3086         if _get(encoding, channel) is not Undefined:
-> 3087             raise ValueError(
   3088                 "Faceted charts cannot be layered. Instead, layer the charts before faceting."
   3089             )
   3090 if isinstance(spec, (Chart, LayerChart)):
   3091     return

ValueError: Faceted charts cannot be layered. Instead, layer the charts before faceting.

Can someone help me, I want to do something like this but with the grouped bars:

enter image description here

Thank you!

I tried to concat the graphs, create both graphics in a base, but I couldn't get what I want.


Solution

  • The error message points you in the right direction: you need to do faceting after layering. For your spec, that means replacing the column encoding with a .facet method on the layered spec. See this section of the docs for an example https://altair-viz.github.io/user_guide/compound_charts.html#faceted-charts