How to add layers to a faceted chart in Altair?

混江龙づ霸主 提交于 2020-02-24 17:02:10

问题


Altair is a lovely visualization lib, with nice intuitive visual grammar API. I am however struggling adding a layer with rule marks to a faceted chart.

Imagine you have a simple dataset:

print(df[['Year', 'Profile', 'Saison', 'Pos']].to_csv())
,Year,Profile,Saison,Pos
0,2017,6.0,Sommer,VL
1,2017,6.0,Winter,VL
13,2017,6.0,Winter,HL
12,2017,6.0,Sommer,HL
18,2017,6.0,Sommer,HR
6,2017,6.0,Sommer,VR
7,2017,6.0,Winter,VR
19,2017,6.0,Winter,HR
14,2018,5.5,Winter,HL
8,2018,5.5,Winter,VR
15,2018,5.5,Sommer,HL
20,2018,4.3,Winter,HR
21,2018,5.0,Sommer,HR
3,2018,5.5,Sommer,VL
2,2018,6.2,Winter,VL
9,2018,4.5,Sommer,VR
17,2019,4.5,Sommer,HL
11,2019,4.2,Sommer,VR
22,2019,3.5,Winter,HR
10,2019,5.28,Winter,VR
5,2019,4.6,Sommer,VL
4,2019,4.9,Winter,VL
16,2019,4.0,Winter,HL
23,2019,4.5,Sommer,HR

Than you can simply display it with:

base = alt.Chart(df[df.Saison=='Winter']).mark_bar().encode(x='Year:O', y='Profile:Q', column='Pos:N')
base

Than, let’s say I want to add horizontal marks to visualize some limits:

For that I define the DataSet:

print(Limits.to_csv())
,Profil
0,3.0
1,1.5

And add it to the collection of charts:

limits = alt.Chart(Limits).mark_rule(color='red').encode(y='Profil')
base + limits

This does not work and generates and error:

ValueError: Faceted charts cannot be layered.

How can I overcome this limitation? Underlying vega-light grammar apparently supports such complex composition of layers, but I cannot figure out the way how to express it in Altair.


回答1:


You cannot layer a facteted chart, because in general there is no guarantee that the contents of each layer contains compatible faceting.

However, you can facet a layered chart. It might look something like this:

import altair as alt
import pandas as pd
import io

df = pd.read_csv(io.StringIO("""
,Year,Profile,Saison,Pos
0,2017,6.0,Sommer,VL
1,2017,6.0,Winter,VL
13,2017,6.0,Winter,HL
12,2017,6.0,Sommer,HL
18,2017,6.0,Sommer,HR
6,2017,6.0,Sommer,VR
7,2017,6.0,Winter,VR
19,2017,6.0,Winter,HR
14,2018,5.5,Winter,HL
8,2018,5.5,Winter,VR
15,2018,5.5,Sommer,HL
20,2018,4.3,Winter,HR
21,2018,5.0,Sommer,HR
3,2018,5.5,Sommer,VL
2,2018,6.2,Winter,VL
9,2018,4.5,Sommer,VR
17,2019,4.5,Sommer,HL
11,2019,4.2,Sommer,VR
22,2019,3.5,Winter,HR
10,2019,5.28,Winter,VR
5,2019,4.6,Sommer,VL
4,2019,4.9,Winter,VL
16,2019,4.0,Winter,HL
23,2019,4.5,Sommer,HR
"""))

bars = alt.Chart().mark_bar().encode(
    x='Year:O',
    y='Profile:Q',
)

limits = alt.Chart(
  pd.DataFrame({'Profil': [3, 1.5]})
).mark_rule(
  color='red'
).encode(y='Profil')

alt.layer(
    bars,
    limits,
    data=df[df.Saison=='Winter']
).facet(
    'Pos:N',
)

Specifying the data here is a little tricky: the facet() method keys-off the top-level data in the chart it's called on, so when you're faceting layers built from different datasets, you need to specify the relevant data at the top level.



来源:https://stackoverflow.com/questions/58624860/how-to-add-layers-to-a-faceted-chart-in-altair

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!