Plotting a Stacked Bar Plot

Single Stacked Bar Chart Matplotlib

First transpose one column DataFrame:

df.T.plot.barh(stacked=True, legend=False)

If 2 or more columns:

df[['Percentage']].T.plot.barh(stacked=True, legend=False)

plotting stacked bar graph

With Python 3.9.7, your graphs look like the same:

>>> df_alpha
a b c d e f g h i j k l
2016 20 20 20 20 20 20 20 20 20 20 20 20
2017 0 13 20 20 20 20 20 20 20 20 20 20
2018 0 10 10 10 10 10 10 10 10 10 10 0
2019 0 18 15 15 15 15 15 15 15 15 15 0
2020 10 15 18 18 18 18 18 18 18 18 18 0
2021 21 45 78 75 78 78 78 78 78 78 78 20

>>> df_month
January February March April may June July August September October November December
2016 20 20 20 20 20 20 20 20 20 20 20 20
2017 0 13 20 20 20 20 20 20 20 20 20 20
2018 0 10 10 10 10 10 10 10 10 10 10 0
2019 0 18 15 15 15 15 15 15 15 15 15 0
2020 10 15 18 18 18 18 18 18 18 18 18 0
2021 21 45 78 75 78 78 78 78 78 78 78 20

Full-code:

import pandas as pd
import matplotlib.pyplot as plt

years = ['2016', '2017', '2018', '2019', '2020', '2021']

dataavail1 = {'a': [20, 0, 0, 0, 10, 21], 'b': [20, 13, 10, 18, 15, 45], 'c': [20, 20, 10, 15, 18, 78], 'd': [20, 20, 10, 15, 18, 75], 'e': [20, 20, 10, 15, 18, 78], 'f': [20, 20, 10, 15, 18, 78], 'g': [20, 20, 10, 15, 18, 78], 'h': [20, 20, 10, 15, 18, 78], 'i': [20, 20, 10, 15, 18, 78], 'j': [20, 20, 10, 15, 18, 78], 'k': [20, 20, 10, 15, 18, 78], 'l': [20, 20, 0, 0, 0, 20]}

dataavail2 = {'January': [20, 0, 0, 0, 10, 21], 'February': [20, 13, 10, 18, 15, 45], 'March': [20, 20, 10, 15, 18, 78], 'April': [20, 20, 10, 15, 18, 75], 'may': [20, 20, 10, 15, 18, 78], 'June': [20, 20, 10, 15, 18, 78], 'July': [20, 20, 10, 15, 18, 78], 'August': [20, 20, 10, 15, 18, 78], 'September': [20, 20, 10, 15, 18, 78], 'October': [20, 20, 10, 15, 18, 78], 'November': [20, 20, 10, 15, 18, 78], 'December': [20, 20, 0, 0, 0, 20]}

df_alpha = pd.DataFrame(dataavail1, index=years)
df_month = pd.DataFrame(dataavail2, index=years)

fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 8))
df_alpha.plot(kind='bar', stacked=True, colormap=plt.cm.tab20, ax=ax1, rot=0)
df_month.plot(kind='bar', stacked=True, colormap=plt.cm.tab20, ax=ax2, rot=0)
plt.show()

Sample Image

Update: the code also works with Python 3.7.12

plotting multiple stacked bar chart

IIUC, try:

import matplotlib.pyplot as plt

fig, ax = plt.subplots(1, 5, figsize=(20, 8))
iax = iter(ax.flatten())
for n, g in df.groupby('Business Unit'):
g.loc[n, :].plot.bar(ax=next(iax), title=f'{n}', stacked=True)

Sample Image

Draw a stacked bar chart from multiple columns instead of drawing a graph for each column?

It can be achieved by rearranging the dataframe using groupby. Consider the code:

df_responses= pd.read_csv('https://raw.githubusercontent.com/eng-aomar/Security_in_practice/main/secuirtyInPractice.csv')

df_new =df_responses.iloc[:,9:21]
image_format = 'svg' # e.g .png, .svg, etc.

# initialize empty dataframe
df2 = pd.DataFrame()

# group by each column counting the size of each category values
for col in df_new:
grped = df_new.groupby(col).size()
grped = grped.rename(grped.index.name)
df2 = df2.merge(grped.to_frame(), how='outer', left_index=True, right_index=True)

# plot the merged dataframe
df2.plot.bar(stacked=True)
plt.show()

Using your data and notebook. This is what I get:

Stacked Bar Plot

Stacked Bar Graphs with only Plotly Express

You can create a dataframe and structure it from your lists. Then it's simple to use Plotly Express

import plotly.express as px
import pandas as pd

labels = ["label1", "label2", "label3"]
types = ["type1", "type2", "type3", "type4", "type5", "type6"]
counts = [[3, 5, 2, 1, 7, 10], [2, 2, 4, 1, 7, 2], [1, 6, 8, 11, 2, 3]]

px.bar(
pd.DataFrame(counts, columns=types, index=labels).reset_index().melt(id_vars="index"),
x="index",
y="value",
color="variable",
)

Sample Image

numpy

import numpy as np

c = np.array(counts)
px.bar(x=np.tile(labels, c.shape[1]), color=np.repeat(types, c.shape[0]), y=c.T.flatten())

Matplotlib stacked bar chart set column order

to set a custom order for the stacked bars, you will need to order it by setting the CategoricalIndex and sorting the data by these categories. This will sort the three categories in the way you need. A small example to show the same is below...

Data 'df'

Intervention    Remuneration    Training    Supervision
A 21 4 12
B 41 5 21
C 33 6 7

Code

#Convert Intervention as index, so columns are the categories
df = df.set_index('Intervention')

#Set categories... Order will Remuneration-Training-Supervision
df.columns=pd.CategoricalIndex(df.columns.values, ordered=True, categories=['Remuneration','Training','Supervision'])

#Sort the data
df = df.sort_index(axis=1)

#...and plot
bar = df.plot.barh(stacked=True)

Output

Sample Image

How to implement stacked bar graph with a line chart in R

You first need to reshape longer, for example with pivot_longer() from tidyr, and then you can use ggplot2 to plot the bars and the line in two separate layers. The fill = argument in the geom_bar(aes()) lets you stratify each bar according to a categorical variable - name is created automatically by pivot_longer().

library(ggplot2)
library(tidyr)

dat |>
pivot_longer(A:B) |>
ggplot(aes(x = Year)) +
geom_bar(stat = "identity", aes(y = value, fill = name)) +
geom_line(aes(y = `C(%)`), size = 2)

Sample Image

Created on 2022-06-09 by the reprex package (v2.0.1)

You're asking for overlaid bars, in which case there's no need to pivot, and you can add separate layers. However I would argue that this could confuse or mislead many people - usually in stacked plots bars are stacked, not overlaid, so thread with caution!

library(ggplot2)
library(tidyr)

dat |>
ggplot(aes(x = Year)) +
geom_bar(stat = "identity", aes(y = A), fill = "lightgreen") +
geom_bar(stat = "identity", aes(y = B), fill = "red", alpha = 0.5) +
geom_line(aes(y = `C(%)`), size = 2) +
labs(y = "", caption = "NB: bars are overlaid, not stacked!")

Sample Image

Created on 2022-06-09 by the reprex package (v2.0.1)



Related Topics



Leave a reply



Submit