Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to modify edge color of Violinplot using Seaborn

Tags:

python

seaborn

I'm trying to change the edge color of violins in Seaborn. And the code below, worked for me.

ax=sns.violinplot(data=df, x="#", y="SleepAmount", hue="Thr", palette=my_pal, split=True,linewidth = 1, inner=None)
ax2 = sns.pointplot(x="#", y="SleepAmount", hue="Thr", data=df, dodge=0.3, join=False, palette=['black'], ax=ax,errwidth=1, ci="sd", markers="_") plt.setp(ax.collections, edgecolor="k") 
plt.setp(ax2.collections, edgecolor="k")

But when I use facetgrid, I have no idea how to adopt plt.setp(ax.collections, edgecolor="k") into facetgrid map below.

g = sns.FacetGrid(df, col="temperature",sharey=True)
g=g.map(sns.violinplot,"#", "latency", "Thr", palette=my_pal, split=True, linewidth = 1, inner=None,data=df)
g=g.map(sns.pointplot, "#", "latency", "Thr", data=df, dodge=0.3, join=False, palette=['black'],errwidth=1, ci="sd", markers="_")

I've tried so many thing. like,

sns.set_edgecolor('k')   
sns.set_style( {"lines.color": "k"})
sns.set_collections({'edgecolor':'k'})
g.fig.get_edgecolor()[0].set_edge("k")
g.setp.get_collections()[0].set_edgecolor("k")

can anyone help me out?

One more quick question, Is it possible to change grid color other than whitegrid nor darkgrid? Facecolor does not work for me since it colors all the background including ticks and labels area. I just want to change only the grid area. Thank you!

like image 902
Jeonghee Ahn Avatar asked Feb 05 '23 00:02

Jeonghee Ahn


2 Answers

Quoting seaborn's documentation for violinplot:

linewidth : float, optional Width of the gray lines that frame the plot elements.

So it looks pretty hardcoded.

As a matter of fact, quoting seaborn's draw violins code:

def draw_violins(self, ax):
    """Draw the violins onto `ax`."""
    fill_func = ax.fill_betweenx if self.orient == "v" else ax.fill_between
    for i, group_data in enumerate(self.plot_data):

        kws = dict(edgecolor=self.gray, linewidth=self.linewidth)

So I guess you can't do that easily with seaborn's API. Or if you're into hacking/monkey patching the seaborn's classes ...

import seaborn.categorical
seaborn.categorical._Old_Violin = seaborn.categorical._ViolinPlotter

class _My_ViolinPlotter(seaborn.categorical._Old_Violin):

    def __init__(self, *args, **kwargs):
        super(_My_ViolinPlotter, self).__init__(*args, **kwargs)
        self.gray='red'

seaborn.categorical._ViolinPlotter = _My_ViolinPlotter

import seaborn as sns
import matplotlib.pyplot as plt


sns.set(style="ticks", color_codes=True)
tips = sns.load_dataset("tips")
g = sns.FacetGrid(tips, col="time", row="smoker")
g.map(sns.violinplot, "tip")
plt.show()

enter image description here

However, seaborn's FacetGrid is based on matplotlib's subplots. Maybe there is a trick to change the diagram once it is prepared for drawing.

like image 134
LoneWanderer Avatar answered Feb 06 '23 13:02

LoneWanderer


Actually you were already quite close (or maybe this did not work back then). Anyway, you can get the axis object from the FacetGrid and then set the edge color for the first entry in its collections like:

import seaborn as sns


tips = sns.load_dataset('tips')
grid = sns.FacetGrid(tips, col="time", row="smoker") 
grid.map(sns.violinplot, "tip", color='white') 

for ax in grid.axes.flatten():
    ax.collections[0].set_edgecolor('red')

which gives enter image description here

like image 34
zeawoas Avatar answered Feb 06 '23 13:02

zeawoas