Reputation: 289
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
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