m13op22
m13op22

Reputation: 2337

How can I adjust the size of the whiskers in a Seaborn boxplot?

I'd like to make the whisker lines wider in the following boxplot.

import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt

data = pd.DataFrame({'Data': np.random.random(100), 'Type':['Category']*100})

fig, ax = plt.subplots()

# Plot boxplot setting the whiskers to the 5th and 95th percentiles
sns.boxplot(x='Type', y='Data', data=data, color = 'gray', whis = [5,95])

# Adjust boxplot and whisker line properties
for p, artist in enumerate(ax.artists):
    artist.set_edgecolor('blue')
    for q in range(p*6, p*6+6):
        line = ax.lines[q]
        line.set_color('pink')

enter image description here

I know how to adjust the whisker color and linewidth, but I haven't been able to figure out how to increase the length of the whiskers. The closest I've come is trying to use line.set_xdata([q/60-0.5, q/60+0.5]) but I get the error

ValueError: shape mismatch: objects cannot be broadcast to a single shape    

Ideally, I'd like to have the whisker percentile lines be the same width as the box. How can I do this?

Upvotes: 4

Views: 2828

Answers (1)

tmdavison
tmdavison

Reputation: 69136

As you have noticed, there are 6 lines plotted for each box (hence your p*6 indexing).

The line with index p*6+4 has the width of the box (that's the median line inside the box). So we can use that to set the widths of the other lines.

The lines you want to change have the index p*6+2 and p*6+3.

import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt

data = pd.DataFrame({'Data': np.random.random(100), 'Type':['Category']*100})

fig, ax = plt.subplots()

# Plot boxplot setting the whiskers to the 5th and 95th percentiles
sns.boxplot(x='Type', y='Data', data=data, color = 'gray', whis = [5,95])

# Adjust boxplot and whisker line properties
for p, artist in enumerate(ax.artists):
    artist.set_edgecolor('blue')
    for q in range(p*6, p*6+6):
        line = ax.lines[q]
        line.set_color('pink')

    ax.lines[p*6+2].set_xdata(ax.lines[p*6+4].get_xdata())
    ax.lines[p*6+3].set_xdata(ax.lines[p*6+4].get_xdata())

enter image description here

This also works with an example with multiple boxes:

import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt

sns.set(style="whitegrid")
tips = sns.load_dataset("tips")
ax = sns.boxplot(x="day", y="total_bill", data=tips)

# Adjust boxplot and whisker line properties
for p, artist in enumerate(ax.artists):
    artist.set_edgecolor('blue')
    for q in range(p*6, p*6+6):
        line = ax.lines[q]
        line.set_color('pink')

    ax.lines[p*6+2].set_xdata(ax.lines[p*6+4].get_xdata())
    ax.lines[p*6+3].set_xdata(ax.lines[p*6+4].get_xdata())

enter image description here

Upvotes: 4

Related Questions