Seaborn Box Plot Whiskers Not Matching Calculations

Viewed 242

The Q3+1.5*IQR portion of the box plot does not match the actual calculation and trying to figure out why. I show that it should be 10.24 but the plot shows about 8.5. Wondering if I am missing something obvious or something else is going on. I deliberately put whis=1.5 as an argument.

state = pd.read_csv('https://raw.githubusercontent.com/gedeck/practical-statistics-for-data-scientists/master/data/state.csv')

sns.boxplot(state['Murder.Rate'], whis=1.5)

q_25 = state['Murder.Rate'].quantile(.25)
q_75 = state['Murder.Rate'].quantile(.75)
max_val = state['Murder.Rate'].max()
min_val = state['Murder.Rate'].min()
iqr = q_75 - q_25
iqr_neg = q_25-1.5*iqr if (q_25-1.5*iqr)>min_val else min_val
iqr_pos = q_75+1.5*iqr if (q_75+1.5*iqr)<max_val else max_val

print('IQR:', iqr)
print('LOWER END:', iqr_neg)
print('UPPER END:', iqr_pos)
print('MIN:',min_val)
print('MAX:',max_val)

output

IQR: 3.125
LOWER END: 0.9
UPPER END: 10.2375
MIN: 0.9
MAX: 10.3

enter image description here

1 Answers

This is because seaborn flags 10.3 as an outlier. With whis=1.5, this is the outlier threshold:

whis = 1.5
q_75 + whis*iqr

# 10.2375

If you remove value 10.3 (index 17) when computing iqr_pos, you'll also get 8.6 as reflected in the boxplot:

state.loc[17, 'Murder.Rate'] = np.nan
iqr_pos = q_75+1.5*iqr if (q_75+1.5*iqr)<max_val else max_val

# 8.6

Or you can stop seaborn from flagging 10.3 as an outlier by increasing whis:

sns.boxplot(x=state['Murder.Rate'], whis=1.6)

whis=2

Related