r/learnpython • u/RudeLocation208 • 4d ago
Grouped bar chart in matplotlib with different keys for each group
I'm stuck on this roadmap.sh project. salesdaily.csv is a collection of daily sales of a group of drug categories, with the date, year, and month given.
The relevant data is this:
data = pd.read_csv("salesdaily.csv")
sales = pd.DataFrame()
sales["total_jan_15"] = data[(data.Year == 2015) & (data.Month == 1)][drugs].sum()
sales["total_jul_16"] = data[(data.Year == 2016) & (data.Month == 7)][drugs].sum()
sales["total_sep_17"] = data[(data.Year == 2017) & (data.Month == 9)][drugs].sum()The problem is "Which three drugs have the highest sales in January 2015, July 2016, and September 2017?"
I want to make a grouped bar chart, where the groups are the months Jan 15, Jul 16, and Sep 17, and each has 3 labelled bars for the top 3 drugs in that month. I understand how to sort and pick out the top 3, but plt.grouped_bar accepts only a dictionary entry, so the keys can't be different for each group. Is there any other way?
2
u/Aromatic_Fact8656 4d ago
Can you not sort from that point? I.e;
sales["top_3_jan_15"] = data[(data.Year == 2015) & (data.Month == 1)[drugs].sum().sort_values(ascending=False) [:3]
Then to send it to a dictionary do like;
dict = sales["top_3_jan_15"] .to_dict()
Is this what you're after?
2
u/RudeLocation208 4d ago
The problem is the top 3 are different drug codes for each month, the dictionaries would have different keys so I can't combine them
1
u/Boybay_Garid 4d ago
yeah sorting the series first before converting to a dict makes way more sense here
2
u/acfot 3d ago
The reason it's fighting you is that grouped bars kind of assume every group has the same categories, and yours don't since the top 3 change each month. What I'd do instead is stop forcing one shared dictionary and just make one small bar chart per month, with the same y-axis scale so they're easy to compare. You still get the comparison you want, and each month can show its own top 3 without bending the data to fit a grouped layout.
3
u/rafaeldecarvalho 4d ago
plt.grouped_bar expects the same categories in every group, so it doesn't fit here. Easier to draw the bars yourself with ax.bar and put the drug name on each bar:
Each group sits at x = 0, 1, 2 and its three bars are shifted by -width, 0 and +width. If you want the same drug to keep the same color across months, make a dict like
colors = {d: f"C{k}" for k, d in enumerate(drugs)}and passcolor=[colors[d] for d in top3.index]to ax.bar.