Search code examples
pythonpandasseaborn

How to make black borders around certain markers in a seaborn pairplot


I have the following code:

import seaborn as sns
import pandas as pd
import numpy as np

Data = pd.DataFrame(columns=['x1','x2','x3','label'])
for i in range(100):
    Data.loc[len(Data.index)] = [np.random.rand(),np.random.rand(),np.random.rand(),'1']

Data.loc[len(Data.index)] = [np.random.rand(),np.random.rand(),np.random.rand(),'2']
Data.loc[len(Data.index)] = [np.random.rand(),np.random.rand(),np.random.rand(),'3']
Data.loc[len(Data.index)] = [np.random.rand(),np.random.rand(),np.random.rand(),'4']
Data.loc[len(Data.index)] = [np.random.rand(),np.random.rand(),np.random.rand(),'5']

sns.pairplot(Data,vars=['x1','x2','x3'],hue='label',markers=['o','s','s','s','s'],corner=True)

Which gives the following output: enter image description here

I want to put black borders only around the square markers to make them more visible but I don't know how to do that.

I tried to add:

grid_kws={fillstyles:['none','full','full','full','full']}

as an argument to sns.pairplot, but I just got the following error:

Traceback (most recent call last):

  File ~/anaconda3/lib/python3.10/site-packages/spyder_kernels/py3compat.py:356 in compat_exec
    exec(code, globals, locals)

  File ~/Dokument/Python/MasterProjectCoCalc/SNmasterproject/untitled0.py:21
    sns.pairplot(Data,vars=['x1','x2','x3'],hue='label',markers=['o','s','s','s','s'],corner=True,grid_kws={fillstyles:['none','full','full','full','full']})

NameError: name 'fillstyles' is not defined

I also tried to add:

plot_kws={'edgecolor':'black'}

to the sns.pairplot function and then I got enter image description here

but now all the points have a black border. How do I get only black borders around the square markers?


Solution

  • The scatter dots are stored in ax.collections[0]. To avoid that the colors of later hue values always come on top, seaborn keeps the dots in the order they appear in the dataframe. You can use .set_edgecolors() to set the edge color of each individual dot.

    For the legend, the dots in stored in its handles as line objects, which you can change via .set_markeredgecolor(...)

    Here is how the code could look like:

    import seaborn as sns
    import pandas as pd
    import numpy as np
    
    Data = pd.DataFrame(columns=['x1', 'x2', 'x3', 'label'])
    for i in range(100):
        Data.loc[len(Data.index)] = [np.random.rand(), np.random.rand(), np.random.rand(), '1']
    Data.loc[len(Data.index)] = [np.random.rand(), np.random.rand(), np.random.rand(), '2']
    Data.loc[len(Data.index)] = [np.random.rand(), np.random.rand(), np.random.rand(), '3']
    Data.loc[len(Data.index)] = [np.random.rand(), np.random.rand(), np.random.rand(), '4']
    Data.loc[len(Data.index)] = [np.random.rand(), np.random.rand(), np.random.rand(), '5']
    
    g = sns.pairplot(Data, vars=['x1', 'x2', 'x3'], hue='label', markers=['o', 's', 's', 's', 's'], corner=True)
    
    edge_colors = ['none' if l == '1' else 'k' for l in Data['label']]
    for ax in g.axes.flat:
        if ax is not None and len(ax. Collections) > 0:
            ax.collections[0].set_edgecolors(edge_colors)
    for h in g.legend.legend_handles[1:]:
        h.set_markeredgecolor('k')
    

    sns.pairplot change individual marker edge colors