How to get markers with no fill, from seaborn 0.11+

Question:

matplotlib.pyplot.scatter() has a facecolors=None argument that will give datapoints the appearance of being hollow on the inside. How to get the same look for seaborn.jointplot()?

The same argument was found in previous versions of seaborn but was removed for some reason in the latest version (0.11).

Asked By: develarist

||

Answers:

  • Since seaborn is a high-level API for matplotlib, this seems to mirror functionality in matplotlib
  • According to an example in the JointGrid documentation, the parameter is fc. To use fc, ec should also be used.
    • Specifying fc='none', without specifying ec, will result in blank markers.
    • fc: facecolor, ec: edgecolor
  • 'None' and 'none' both work, but not None.
  • Tested in python 3.10, matplotlib 3.5.1, seaborn 0.11.2
import seaborn as sns

# load data
df = sns.load_dataset("penguins", cache=False)

# plot
g = sns.jointplot(data=df, x="bill_length_mm", y="bill_depth_mm",
                  ec="purple", fc="none", color='purple')

enter image description here

  • As pointed out in the answer from a11, ec requires more than a single color if using the hue= parameter. However, it’s easier to create palette by zipping the unique values from the column passed to hue, to a known color palette, for anything more than a couple of colors.
    • palette = dict(zip(df.species.unique(), sns.color_palette('tab10')))
      • 'tab10' is the default
    • species = df.species.unique() and palette = dict(zip(species, sns.color_palette('crest', n_colors=len(species))))
      • If using continuous palettes, specifying n_colors will generate a palette with better color differentiation.
# load data
df = sns.load_dataset("penguins")

# create a palette dict with a known color_palette
species = df.species.unique()
palette = dict(zip(species, sns.color_palette(palette='crest', n_colors=len(species))))

# ec requires a single value or a list of values
ec = penguins.species.map(palette)

# plot
g = sns.jointplot(data=df, x="bill_length_mm", y="bill_depth_mm",
                  hue='species', ec=ec, fc="none", palette=palette)

enter image description here


Palettes

'Accent', 'Accent_r', 'Blues', 'Blues_r', 'BrBG', 'BrBG_r', 'BuGn', 'BuGn_r', 'BuPu'
'BuPu_r', 'CMRmap', 'CMRmap_r', 'Dark2', 'Dark2_r', 'GnBu', 'GnBu_r', 'Greens', 'Greens_r'
'Greys', 'Greys_r', 'OrRd', 'OrRd_r', 'Oranges', 'Oranges_r', 'PRGn', 'PRGn_r', 'Paired'
'Paired_r', 'Pastel1', 'Pastel1_r', 'Pastel2', 'Pastel2_r', 'PiYG', 'PiYG_r', 'PuBu'
'PuBuGn', 'PuBuGn_r', 'PuBu_r', 'PuOr', 'PuOr_r', 'PuRd', 'PuRd_r', 'Purples', 'Purples_r'
'RdBu', 'RdBu_r', 'RdGy', 'RdGy_r', 'RdPu', 'RdPu_r', 'RdYlBu', 'RdYlBu_r', 'RdYlGn'
'RdYlGn_r', 'Reds', 'Reds_r', 'Set1', 'Set1_r', 'Set2', 'Set2_r', 'Set3', 'Set3_r'
'Spectral', 'Spectral_r', 'Wistia', 'Wistia_r', 'YlGn', 'YlGnBu', 'YlGnBu_r', 'YlGn_r'
'YlOrBr', 'YlOrBr_r', 'YlOrRd', 'YlOrRd_r', 'afmhot', 'afmhot_r', 'autumn', 'autumn_r'
'binary', 'binary_r', 'bone', 'bone_r', 'brg', 'brg_r', 'bwr', 'bwr_r', 'cividis'
'cividis_r', 'cool', 'cool_r', 'coolwarm', 'coolwarm_r', 'copper', 'copper_r', 'crest'
'crest_r', 'cubehelix', 'cubehelix_r', 'flag', 'flag_r', 'flare', 'flare_r', 'gist_earth'
'gist_earth_r', 'gist_gray', 'gist_gray_r', 'gist_heat', 'gist_heat_r', 'gist_ncar'
'gist_ncar_r', 'gist_rainbow', 'gist_rainbow_r', 'gist_stern', 'gist_stern_r', 'gist_yarg'
'gist_yarg_r', 'gnuplot', 'gnuplot2', 'gnuplot2_r', 'gnuplot_r', 'gray', 'gray_r'
'hot', 'hot_r', 'hsv', 'hsv_r', 'icefire', 'icefire_r', 'inferno', 'inferno_r', 'jet'
'jet_r', 'magma', 'magma_r', 'mako', 'mako_r', 'nipy_spectral', 'nipy_spectral_r'
'ocean', 'ocean_r', 'pink', 'pink_r', 'plasma', 'plasma_r', 'prism', 'prism_r', 'rainbow'
'rainbow_r', 'rocket', 'rocket_r', 'seismic', 'seismic_r', 'spring', 'spring_r', 'summer'
'summer_r', 'tab10', 'tab10_r', 'tab20', 'tab20_r', 'tab20b', 'tab20b_r', 'tab20c'
'tab20c_r', 'terrain', 'terrain_r', 'turbo', 'turbo_r', 'twilight', 'twilight_r', 'twilight_shifted'
'twilight_shifted_r', 'viridis', 'viridis_r', 'vlag', 'vlag_r', 'winter', 'winter_r'
Answered By: Trenton McKinney

If you want to be able to leverage the hue parameter, here is a way that builds off @Trenton’s answer. First, define your colormap. Second, set your appropriate hue and specify the colormap in the palette and edgecolor parameters.

penguins = sns.load_dataset("penguins")

colormap = {"Adelie": "purple", "Chinstrap": "orange", "Gentoo": "green"}

sns.jointplot(
    data=penguins,
    x="bill_length_mm",
    y="bill_depth_mm",
    hue="species",
    palette=colormap,
    ec=penguins["species"].map(colormap),
    fc="none",
)

enter image description here

Answered By: a11