Search code examples
pythonvisualizationaltair

In Alt HConcat , is it possible to define strokeWidth individually for each (i.e. not use configure_* , which can only be applied to Top level)?


I have a need to have a left side faceted chart (using mark_rect) that has several small-multiples/mini charts. On the right, I would like to label them by their title using mark_text. The concatenation works fine using (left | right) , however I have a need to remove the box that is on the view from mark_text

Example code describing my is below:

import altair as alt
import pandas as pd

df = pd.DataFrame(
[['BookA',0,'Hello',3],
['BookA',0,'World',1],
['BookA',1,'Hello',1],
['BookA',1,'World',0],
['BookA',2,'Hello',4],
['BookA',2,'World',2],
['BookB',0,'Hello',0],
['BookB',0,'World',0],
['BookB',1,'Hello',2],
['BookB',1,'World',3],
['BookC',0,'Hello',1],
['BookC',0,'World',0],
['BookC',1,'Hello',1],
['BookC',1,'World',2],
['BookC',2,'Hello',3],
['BookC',2,'World',4],
['BookC',3,'Hello',0],
['BookC',3,'World',0],
], columns = ['title','line','var','val']
)

base = alt.Chart(df)

#    Left chart containing heatmap
left = base.mark_rect().encode(
    x=alt.X('line:O',axis=alt.Axis(tickSize=0,labels=False,title="",domain=False)),
    y=alt.Y('var:O',axis=alt.Axis(tickSize=0,title="",labelFontSize = 12,labelPadding = 6,domain=False)),
    color= alt.Color('val:O',scale=alt.Scale(scheme="blues"),legend=None),
    facet=alt.Facet('title:N', columns=1,header=alt.Header(labelExpr="''",labelOrient="right",title=""))
    ).resolve_scale(
    x='independent' #Make each plot have scale of x-axis only as per desired length
    ).properties(height = 50)
    
#    Right chart containing Book title
right = base.mark_text(strokeOpacity = 1, 
                                                dx= 300, #Added to shift by right
                                                fontSize = 14,fontWeight = 'normal', baseline='top').encode(
    text = alt.Text('title'),
    facet=alt.Facet('title:N', columns=1,header=alt.Header(labelExpr="''",labelOrient="right",title=""))
    ).properties(height = 51)

(left | right).configure_view(stroke='black',strokeWidth=2)

I would ideally like to remove the black bordered boxes that appear in the middle. If I set strokeWidth = 0 in configure_view, it affects the left visualization in the below image, which I do not wish to.Black border issue


Solution

  • You could manually edit the properties of the chart object instead of using the configure_view method. This means you can add it to the view property of the chart dictionary instead of using config.view (not sure if this could have side effects):

    left.view = {}
    left.view['stroke'] = 'black'
    left.view['strokeWidth'] = 3
    (left | right).configure_view(stroke=None)
    

    enter image description here

    Also note that if you use alt.hconcat there is a padding parameter that can achieve what you are doing with dx now, note sure if there is an advantage practically in your case, but its purpose is to separate concatenated plots so might be useful to know of in general.