Pete
Pete

Reputation: 289

Coloring bar chart by category of the values

I need to color my bar plot by the values' category. Is that possible using Matplotlib?

Example: Normally I use two list to create a bar chart: values = [5, 2, 1, 7, 8, 12] xticks = [John, Nina, Darren, Peter, Joe, Kendra]

Is it possible to add an extra category list, and color those bars based on those categories? Like: category = [male, female, male, male, male, female]

Thanks in advance!

Upvotes: 1

Views: 2406

Answers (1)

Asmus
Asmus

Reputation: 5257

If you want, you could structure your data as a dictionary, then it could be solved like this, where each entry as a property "gender" which is also the lookup key in the dictionar color_map :

import matplotlib.pyplot as plt

fig,ax=plt.subplots(1,1)

data={
    0:{"name":"John",   "value":5, "gender":"male"},
    1:{"name":"Nina",   "value":2, "gender":"female"},
    2:{"name":"Darren", "value":1, "gender":"male"},
    3:{"name":"Peter",  "value":7, "gender":"male"},
    4:{"name":"Joe",    "value":8, "gender":"male"},
    5:{"name":"Kendra", "value":12,"gender":"female"},
}

color_map={"male":"b","female":"r"}

xs=data.keys()
ys=[v["value"] for v in data.values()]
names=[v["name"] for v in data.values()]
colors=[color_map[v["gender"]] for v in data.values()]

ax.bar(xs,ys,color=colors)

ax.set_xticks(xs)
ax.set_xticklabels(names)
plt.show()

There are multiple ways to get a valid "male"/"female" legend here; one would be to create a fully custom legend. Apart form that you could, for example, separate the dict into one for male and one for female data, and then create two separate bar plots like ax.bar(… , label="male"), which is kind of a bloated approach, however.

I'd suggest to use the pandas library then, changing my answer to:

import matplotlib.pyplot as plt
import pandas as pd

fig,ax=plt.subplots(1,1)

data={
    0:{"name":"John",   "value":5, "gender":"male"},
    1:{"name":"Nina",   "value":2, "gender":"female"},
    2:{"name":"Darren", "value":1, "gender":"male"},
    3:{"name":"Peter",  "value":7, "gender":"male"},
    4:{"name":"Joe",    "value":8, "gender":"male"},
    5:{"name":"Kendra", "value":12,"gender":"female"},
}

df=pd.DataFrame.from_dict(data,orient='index')

color_map={"male":"b","female":"r"}
df["colors"]=df["gender"].map(color_map)

for g in ["male","female"]:
    xs=df.index[df["gender"]==g]
    ys=df["value"][df["gender"]==g]
    color=df["colors"][df["gender"]==g]
    ## or, perhaps easier in this specific case: 
    #  color=color_map[g]

    ax.bar(xs,ys,color=color,label=g)

ax.legend()
ax.set_xticks(df.index)
ax.set_xticklabels(df["name"])

plt.show()

Here, the key is that we can filter the dataframe df (think of it perhaps like an Excel worksheet) on various conditions, e.g. df["value"][df["gender"]=="male"]. This way we can create the two separate bar plots easily.

Upvotes: 1

Related Questions