Search code examples
pythonmatplotlibfunctional-programmingseabornvisualization

Seaborn Object Interface: custom title and facet with 2 or more variables


I am using seaborn object interface and I want to go a little further in graph customization. Here is a case with facet plot on 2 observations:

df = pd.DataFrame(
    np.array([['A','B','A','B'],['odd','odd','even','even'], [1,2,1,2], [2,4,1.5,3],]).T
    , columns= ['kind','face','Xs','Ys']
    )
(
    so.Plot(df,x='Xs' , y='Ys')
    .facet("kind","face")
    .add(so.Dot())
    .label(title= 'kind :{}'.format)
)

facet plot on 2 observations with seaborn object interface

As you can see, subplots title display "kind: | kind: ". I want to display "kind: | face: ".

Obviously I tried title= 'kind :{}, face :{}'.format but it threw an error...

I discovered .label(title= 'kind :{}'.format) iterates over facet observation inputs and made a quick and dirty workaround.

df = pd.DataFrame(
    np.array([['A','B','A','B'],['odd','odd','even','even'], [1,2,1,2], [2,4,1.5,3],]).T
    , columns= ['kind','face','Xs','Ys']
    )
def multiObs_facet_title(t:tuple) -> str:
    if t in ['A','B']:
        return 'kind: {}'.format(t)
    else:
        return 'face: {}'.format(t)
(
    so.Plot(df,x='Xs' , y='Ys')
    .facet("kind","face")
    .add(so.Dot())
    .label(title= multiObs_facet_title)
)

naming according to facet observations

I wonder if there is a better way to do this without to have checking the value of observations?


Solution

  • It's probably not what you are looking for. But with a 2-D Seaborn facet (columns and rows), it doesn't seem too bad to do it in pandas if you want to avoid defining a custom function.

    df = pd.DataFrame(
        np.array([['A','B','A','B'],['odd','odd','even','even'], [1,2,1,2], [2,4,1.5,3],]).T
        , columns= ['kind','face','Xs','Ys']
        )
    
    df["kind_1"] = "kind: "+ df["kind"]
    df["face_1"] = "face: "+ df["face"]
    
    (
        so.Plot(df,x='Xs' , y='Ys')
        .facet("kind_1","face_1")
        .add(so.Dot())
    )