Plotting box plots of two columns side by side in seaborn

Viewed 7689

I would like to plot two columns of a pandas dataframe as side by side box plots by category. This is not the same as the question presented in here: Grouped boxplot with seaborn where the two columns have lists inside them. The solution there did not work for me.

MWE

import seaborn as sns
import pandas as pd
import matplotlib.pyplot as plt
df = pd.DataFrame(
[
[2, 4, "A"],
[4, 5, "C"],
[5, 4, "B"],
[10, 4.2, "A"],
[9, 3, "B"],
[3, 3, "C"]
], columns=['data1', 'data2', 'Categories'])

#Plotting by seaborn
fig, axs = plt.subplots(1, 1)
sns.boxplot(data=df,x="Categories",y='data1',ax=axs)
fig.show()
plt.waitforbuttonpress()
plt.close(fig)

The code above generates: enter image description here

Replacing "data1" with "data2" in the boxplot line would give: enter image description here

What I want is something like this: enter image description here

2 Answers

You need to melt (convert to long format) the DataFrame first:

data = df.melt(id_vars=['Categories'], var_name='dataset', value_name='values')
print(data)

Prints:

   Categories dataset  values
0           A   data1     2.0
1           A   data2     4.0
2           C   data1     4.0
3           C   data2     5.0
4           B   data1     5.0
5           B   data2     4.0
6           A   data1    10.0
7           A   data2     4.2
8           B   data1     9.0
9           B   data2     3.0
10          C   data1     3.0
11          C   data2     3.0

Now you just have to use dataset as the hue. Since the plot is quite busy I moved the legend outside it.

sns.boxplot(data=data, x='Categories', y='values', hue='dataset')
plt.legend(title='dataset', loc='upper left', bbox_to_anchor=(1, 1))

enter image description here

Edit by OP:

I implemented this in a function such that it makes the plot with as many columns as desired in an ax and returns it.

def box_plot_columns(df,categories_column,list_of_columns,legend_title,y_axis_title,**boxplotkwargs):
    columns = [categories_column] + list_of_columns
    newdf = df[columns].copy()
    data = newdf.melt(id_vars=[categories_column], var_name=legend_title, value_name=y_axis_title)
    return sns.boxplot(data=data, x=categories_column, y=y_axis_title, hue=legend_title, **boxplotkwargs)

Usage Example:

fig, ax = plt.subplots(1,1)
ax = box_plot_columns(Data,"Categories",["data1","data2"],"dataset","values",ax=ax)
ax.set_title("My Plot")
plt.show()

Try This :

df = pd.DataFrame(
[
[2, 4, "A"],
[4, 5, "C"],
[5, 4, "B"],

[10, 4.2, "A"],
[9, 3, "B"],
[3, 3, "C"]
], columns=['data1', 'data2', 'Categories'])

#Plotting by seaborn
df_c = pd.melt(df, "Categories", var_name="data1", value_name="data2")
sns.factorplot("Categories",hue="data1", y="data2", data=df_c, kind="box")
Related