问题
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