arcanaxion
arcanaxion

Reputation: 23

In matplotlib pyplot, how to group bars in a bar plot by category?

First off, I'm not trying to make a regular grouped bar plot.

I have two arrays such as

user_score = [70, 95, 86, 50, 17]
user_type = ['High', 'High', 'High', 'Mid', 'Low']

I'm trying to create a bar plot such that bars of a same category (user_type in this case) are grouped together by separation or color.

Example image of what I'm trying to achieve

Fig. 1

How do I do this in pyplot?

Currently for my actual use case I'm only able to achieve this:

Fig. 2

Edit:

1.

Actual data:

user_utilisation_rating = [0.0, 0.0, 0.0, 0.06, 0.09, 0.12, 0.13, 0.13, 0.14, 0.14, 0.16, 0.26, 0.3, 0.53, 0.54, 0.56, 0.76, 0.79, 1.0, 1.0]
user_type = ['Minimum', 'Minimum', 'Minimum', 'Consistent low', 'Consistent low', 'Consistent low', 'Consistent low', 'Consistent low', 'Consistent low', 'Consistent low', 'Consistent low', 'Ending low', 'Ending low', 'Start low', 'Start low', 'Start low', 'Consistent high', 'Consistent high', 'Maximum', 'Maximum']

2.

Changed Fig 1 to style more similar to what I'm trying to do with regards to my actual plot in Fig 2.

3.

Trying to accomplish it with this but only 1 bar appears per user_type. Not sure what I'm doing wrong.

import pandas as pd

user_pd = pd.DataFrame({
    'utilisation' : users_utilisation_rating,
    'type' : user_type
})

user_pd.sort_values(by=['utilisation'], inplace=True)

fig, ax = plt.subplots(figsize = (14, 10))

for tp in user_pd['type'].unique():
    ax.bar(user_pd[user_pd['type'] == tp]['type'],
           user_pd[user_pd['type'] == tp]['utilisation'],
           label = tp)

ax.legend()
plt.show()

Upvotes: 2

Views: 366

Answers (2)

Anwarvic
Anwarvic

Reputation: 13022

According to your data, you can do something like this:

color_map = {"Start low": "#581845",
            "Consistent low": "#900C3F",
            "Ending low":"#C70039",
            "Minimum":"#FF5733",
            "Consistent high":"#FFC300",
            "Maximum":"#509916"}


df = pd.DataFrame({"user_rating": user_utilisation_rating,
                  "user_type": user_type})
df.plot.bar(x='user_type', y='user_rating', rot=45,
          color=[color_map[i] for i in user_type])
plt.legend().remove()
plt.show()

Which produces something like this: enter image description here

NOTE: Notice that I've removed the legend as the x-axis does its role

Upvotes: 2

Zephyr
Zephyr

Reputation: 12524

You could loop over unique elements in the 'cylinders' column like this:

import matplotlib.pyplot as plt
import pandas as pd

df = pd.read_csv('mpg.csv')
df.sort_values(by = ['cylinders', 'mpg'], inplace = True)

fig, ax = plt.subplots(figsize = (14, 10))

for cyl in df['cylinders'].unique():
    ax.bar(df[df['cylinders'] == cyl]['name'],
           df[df['cylinders'] == cyl]['mpg'],
           label = cyl)
plt.setp(ax.xaxis.get_majorticklabels(), rotation = 90)
ax.legend()

plt.show()

and get this plot:

enter image description here


Alternatively you can use seaborn.barplot:

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

df = pd.read_csv('mpg.csv')
df.sort_values(by = ['cylinders', 'mpg'], inplace = True)

fig, ax = plt.subplots(figsize = (14, 10))

sns.barplot(x = df['name'],
            y = df['mpg'],
            hue = df['cylinders'],
            dodge = False)
plt.setp(ax.xaxis.get_majorticklabels(), rotation = 90)

plt.show()

and get this plot:

enter image description here


Finally, if you want to improve a little the visualization of the bar, you can use a transparency value:

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

df = pd.read_csv('mpg.csv')
df.sort_values(by = ['cylinders', 'mpg'], inplace = True)

fig, ax = plt.subplots(figsize = (14, 10))

sns.barplot(x = df['name'],
            y = df['mpg'],
            hue = df['cylinders'],
            edgecolor = 'k',
            dodge = False,
            alpha = 0.3)
plt.setp(ax.xaxis.get_majorticklabels(), rotation = 90)

plt.show()

which gives:

enter image description here

Upvotes: 2

Related Questions