-1

I am graphing the following stacked bar chart using matplotlib, and I would like to show the total views (of the entire bar) on top of each stacked bar. This is the code I am using to create the graph:

okrViews = okrs_results['Page Views'].tolist()
blogViews = blog_results['Page Views'].tolist()
landingPageViews = landing_page_results['Page Views'].tolist()
teamsViews = teams_results['Page Views'].tolist()
eventsViews = events_results['Page Views'].tolist()
initiativesViews = initiatives_results['Page Views'].tolist()
toolsViews = tools_results['Page Views'].tolist()
indx = np.arange(len(months))

# Calculate starting position for each bar
okrsAndBlogs = [i+j for i,j in zip(okrViews, blogViews)]
okrsBlogsLanding = [i+j for i,j in zip(landingPageViews, okrsAndBlogs)]
four = [i+j for i,j in zip(teamsViews, okrsBlogsLanding)]
five = [i+j for i,j in zip(eventsViews, four)]
six = [i+j for i,j in zip(initiativesViews, five)]

# Set figure size
plt.figure(figsize=(19,10))

# Add each bar
graphBlogs = plt.bar(x = indx, height = blogViews, width = .45, color='tab:blue', label = 'Blogs')
graphOkrs = plt.bar(x = indx, height = okrViews, width = .45, color='tab:pink', bottom = blogViews, label = 'OKRs')
graphLanding = plt.bar(x = indx, height = landingPageViews, width = .45, color='green', bottom = okrsAndBlogs, label = 'Landing Page')
graphTeams = plt.bar(x = indx, height = teamsViews, width = .45, color='orange', bottom = okrsBlogsLanding, label = 'Teams')
graphEvents = plt.bar(x = indx, height = eventsViews, width = .45, color='tab:olive', bottom = four, label = 'Events')
graphInitiatives = plt.bar(x = indx, height = initiativesViews, width = .45, color='tab:purple', bottom = five, label = 'Initiatives; Risk and Data Privacy')
graphTools = plt.bar(x = indx, height = toolsViews, width = .45, color='tab:cyan', bottom = six, label = 'Tools')

    
# Set labels
plt.xticks(indx, months)
plt.xlabel("Month")
plt.ylabel("Total Views")
plt.title('Views per Day, Grouped by Month, YTD')
plt.legend()

plt.show()

How would I go about doing this? To explain further, I'd like to have ~10,000 above January's stacked bar, ~8,000 above Februarys, and so on. Thanks in advance!

currentChart

Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
etnie1031
  • 81
  • 3
  • 12
  • Based on the implementation of this code, it does not appear to be a correctly stacked bar. While it does use `bottom`, it appears to be more of a layered bar. This is an incorrect, non-standard implementation. Additionally, there is not a complete [mre] with reproducible sample data, which makes the question not very useful to the community. – Trenton McKinney Apr 05 '23 at 02:18
  • In any case, the easiest solution would be to use the last plot alias with `.bar_label`: `_ = graphTools.bar_label(graphTools.containers[-1])`, which would label the top with the full value. See [How to add value labels on a bar chart](https://stackoverflow.com/a/67561982/7758804) and [Stacked Bar Chart with Centered Labels](https://stackoverflow.com/a/60895640/7758804) – Trenton McKinney Apr 05 '23 at 02:28

1 Answers1

1

Update: Figured it out, I just had to sum it up manually, then I used plt.text. In a prior cell, I had initialized months to be a list of the names of the months.

Solution:

monthTotals = []
for month in months:
    total = 0
    total += int(okrs_results[okrs_results['Month'] == month]['Page Views'])
    total += int(blog_results[blog_results['Month'] == month]['Page Views'])
    total += int(landing_page_results[landing_page_results['Month'] == month]['Page Views'])
    total += int(teams_results[teams_results['Month'] == month]['Page Views'])
    total += int(events_results[events_results['Month'] == month]['Page Views'])
    total += int(initiatives_results[initiatives_results['Month'] == month]['Page Views'])
    total += int(tools_results[initiatives_results['Month'] == month]['Page Views'])
    monthTotals.append(total)

okrViews = okrs_results['Page Views'].tolist()
blogViews = blog_results['Page Views'].tolist()
landingPageViews = landing_page_results['Page Views'].tolist()
teamsViews = teams_results['Page Views'].tolist()
eventsViews = events_results['Page Views'].tolist()
initiativesViews = initiatives_results['Page Views'].tolist()
toolsViews = tools_results['Page Views'].tolist()
indx = np.arange(len(months))

# Calculate starting position for each bar
okrsAndBlogs = [i+j for i,j in zip(okrViews, blogViews)]
okrsBlogsLanding = [i+j for i,j in zip(landingPageViews, okrsAndBlogs)]
four = [i+j for i,j in zip(teamsViews, okrsBlogsLanding)]
five = [i+j for i,j in zip(eventsViews, four)]
six = [i+j for i,j in zip(initiativesViews, five)]

# Set figure size
plt.figure(figsize=(19,10))

# Add each bar
graphBlogs = plt.bar(x = indx, height = blogViews, width = .45, color='tab:blue', label = 'Blogs')
graphOkrs = plt.bar(x = indx, height = okrViews, width = .45, color='tab:pink', bottom = blogViews, label = 'OKRs')
graphLanding = plt.bar(x = indx, height = landingPageViews, width = .45, color='green', bottom = okrsAndBlogs, label = 'Landing Page')
graphTeams = plt.bar(x = indx, height = teamsViews, width = .45, color='orange', bottom = okrsBlogsLanding, label = 'Teams')
graphEvents = plt.bar(x = indx, height = eventsViews, width = .45, color='tab:olive', bottom = four, label = 'Events')
graphInitiatives = plt.bar(x = indx, height = initiativesViews, width = .45, color='tab:purple', bottom = five, label = 'Initiatives; Risk and Data Privacy')
graphTools = plt.bar(x = indx, height = toolsViews, width = .45, color='tab:cyan', bottom = six, label = 'Tools')

# Show sum on each stacked bar
for i, v in enumerate(monthTotals):
    if v != 0:
        plt.text(indx[i] - .2, v, str(v))
    
# Set labels
plt.xticks(indx, months)
plt.xlabel("Month")
plt.ylabel("Total Views")
plt.title('Views per Day, Grouped by Month, YTD')
plt.legend()

plt.show()

Result:

Solution

etnie1031
  • 81
  • 3
  • 12