Horizontal barplot in seaborn with numeric independent data

Viewed 11192

This is the Seaborn Doc on how to make a horizontal boxplot. You'll notice that they use some dataset called crashes and are graphing some categorical variable vs some numeric variable. To make it horizontal, they are just flipping the x and y variable, easy enough.

My issue is that my categories are numeric which causes problems. A minimum reproducible example uses their dataset. Basically this should be the same graph one horizontal and the other vertical. As you can see they are both vertical...

import seaborn as sns
import matplotlib.pyplot as plt
sns.set(style="whitegrid")


crashes = sns.load_dataset("car_crashes").sort_values("total", ascending=False)

crashes['roundTotal'] = np.round(crashes['total']).astype(int)
crashesMod = crashes.groupby(['roundTotal']).count().reset_index()
crashesMod['VsAverage'] = crashesMod['total'] > crashesMod.total.mean()

sns.barplot(x = 'roundTotal', y = 'total', hue = 'VsAverage', data = crashesMod)
plt.show()
sns.barplot(y = 'roundTotal', x = 'total', hue = 'VsAverage', data = crashesMod)

enter image description here

I tried making the column 'roundTotal' of type string as I imagined that it was doing some guessing under the hood and was failing with the 2 numeric types, but then I run into TypeError: unsupported operand type(s) for /: 'str' and 'int'

2 Answers

Just add this before plotting:

crashesMod.roundTotal=crashesMod.roundTotal.astype('category')
crashesMod.VsAverage=crashesMod.VsAverage.astype('category')

According the the seaborn docs, you should use the 'orient' option:

import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
sns.set(style="whitegrid")

fig, ax = plt.subplots(figsize=(3.5, 6))

crashes = (
    sns.load_dataset("car_crashes")
        .sort_values("total", ascending=False)
        .assign(roundTotal=lambda df: df['total'].round().astype(int).astype('category'))
        .groupby(['roundTotal']).count()
        .reset_index()
        .assign(VsAverage=lambda df: df['total'] > df['total'].mean())
        .pipe((sns.barplot, 'data'), y='roundTotal', x='total',
              hue='VsAverage', orient='horizonal', ax=ax)
)

ax.invert_yaxis()

And that gives me:

enter image description here

Related