0

I have a dataframe as below

category val1 val2 val3
A       2    3     2
A       3    4     1
B       4    5     2
C       3    3     2
B       4    5     2
C       3    3     2

I am trying to create a grouped bar visual that has category in the x-axis, and val1, val2, val3 as y-axis.

my code is similar to this:

plt.bar(df['category'], df['var1'])
plt.bar(df['category'], df['var2'])
plt.bar(df['category'], df['var3'])

however, I didn't get a grouped bar graph. It is something like this. Is there anyway to fix this?

enter image description here

Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
  • 1
    Your categories aren't unique, so what would you expect to see on the x-axis? – Kris Jan 25 '21 at 00:25
  • Is there anyway to make this category unique – codelearner0504 Jan 25 '21 at 00:27
  • 1
    Do you want to group them somehow or remove duplicates? I don't know your context. – Kris Jan 25 '21 at 00:28
  • Your question is related to pandas, your tags say matplotlib, your title mentions seaborn - what are you looking for? And as Kris already said - what should happen with your duplicate categories? Should they be aggregated as sums or means or appear multiple times? – Mr. T Jan 25 '21 at 00:38
  • Sorry, I am not looking for a stacked bar, but rather a grouped bar. So green, yellow, and blue section should be horizontal – codelearner0504 Jan 25 '21 at 00:57
  • The default is not stacked, so just remove this from the code kindly provided by Kris. But what should happen with the duplicate categories? – Mr. T Jan 25 '21 at 00:59

2 Answers2

2

I'm not sure this is what you are after, but you can try these two options:

import pandas as pd
from io import StringIO
import seaborn as sns

data = """category val1 val2 val3
A       2    3     2
A       3    4     1
B       4    5     2
C       3    3     2
B       4    5     2
C       3    3     2"""

df = pd.read_csv(StringIO(data), sep="\s+")

g = sns.barplot(
    data=df.melt(id_vars = ["category"], value_vars=["val1", "val2", "val3"]),
    y="value", x="variable", hue="category", ci=None
)

enter image description here

or

g = sns.catplot(
    data=df.melt(id_vars = ["category"], value_vars=["val1", "val2", "val3"]),
    kind="bar",
    y="value", x="variable", col="category", ci=None
)
g.set_axis_labels("", "")

enter image description here

The key to these approaches is to use melt to unpivot your data.

Note also that the above is not dealing with your duplicate categories. If you want your values to be unique, you can group your df by category and aggregate values before plotting.

foglerit
  • 7,792
  • 8
  • 44
  • 64
0

Your categories aren't unique. What do you want to see on the x-axis?

Suppose they were unique, then you could simply do:

import pandas as pd
import seaborn as sns
sns.set()

df = pd.DataFrame()
df['category'] = ['A','B','C','D','E','F']
df['val1'] = [2,3,4,3,4,3]
df['val2'] = [3,4,5,3,5,3]
df['val3'] = [2,1,2,2,2,2]

df.set_index('category').plot(kind='bar', stacked=True)

enter image description here


Edit: seaborn doesn't support stacked bar charts natively, but here's a hacky way if you need to (or if others are looking for what's actually in the title).

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
sns.set()

df = pd.DataFrame()
df['category'] = ['A','B','C','D','E','F']
df['val1'] = [2,3,4,3,4,3]
df['val2'] = [3,4,5,3,5,3]
df['val3'] = [2,1,2,2,2,2]

# create total columns
df['v1+v2+v3'] = df.val1 + df.val2 + df.val3
df['v1+v2'] = df.val1 + df.val2

# plot total
g = sns.barplot(x=df['category'], y=df['v1+v2+v3'], color='green', label='val3')

# plot middle values
g = sns.barplot(x=df['category'], y=df['v1+v2'], color='orange', label='val2')

# plot bottom values
g = sns.barplot(x=df['category'], y=df['val1'], color='blue', label='val1')

# rename axes
g.set_ylabel('vals')
g.set_xlabel('categories')

plt.legend()

enter image description here

Kris
  • 564
  • 2
  • 6
  • The title of the question asks for seaborn, no? Or did you mean my answer doesn't explicitly use seaborn to plot? – Kris Jan 25 '21 at 00:36
  • Fair enough, made an edit to reflect what's actually being asked in the question. – Kris Jan 25 '21 at 00:49
  • Sorry, I am not looking for a stacked bar, but rather a grouped bar. So green, yellow, and blue section should be horizontal – codelearner0504 Jan 25 '21 at 00:57