Jeonghee Ahn
Jeonghee Ahn

Reputation: 111

How to modify edge color of Violinplot using 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!

Upvotes: 10

Views: 7244

Answers (2)

zeawoas
zeawoas

Reputation: 466

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

Upvotes: 7

LoneWanderer
LoneWanderer

Reputation: 3341

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.

Upvotes: 7

Related Questions