Waffle charts can be an interesting element in a dashboard. It is especially useful to display the progress towards goals, seeing how each item contributes to the whole. But waffle charts are not very useful if you try to put too many items in it. R, Tableau, and Python each have packages or functions for waffle charts. I will show generating a waffle chart from scratch and also using Waffle function from pywaffle.
Tools to be used
For this tutorial, we will use:
Develop a Waffle Chart Without Waffle Package
- Import the necessary packages:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
2. Create a DataFrame. For this tutorial, I will make a DataFrame that will fakely represent the number of immigrants from Argentina, Brazil, Cuba, and Peru to the US. The numbers are just imaginary.
df = pd.DataFrame({
'country': ['Argentina', 'Brazil', 'Cuba', 'Peru'],
'number': [212, 334, 1500, 130]
})

3. As we will present the contribution to each country’s immigrants number to the total, we need to know the total. Calculate the total:
total = sum(df['number'])
4. Calculate the proportion of each country
proportions = [(float(value) / total) for value in df['number']]#Output:
[0.0974264705882353,
0.15349264705882354,
0.6893382352941176,
0.05974264705882353]
5. Specify the width and height of the chart. Then calculate the total number of tiles in the waffle chart
width = 40
height=10
total= width * height
6. Determine, how many tiles will be allotted to each country
tiles_per_category = [round(proportion * total) for proportion in proportions]#Output:
[39, 61, 276, 24]
7. All the easier work is done. Now the tricky part. Generate the waffle. For that, we will generate a matrix of all zeros. And then replace each zero with the corresponding category. This matrix will resemble the waffle chart.
waffle = np.zeros((height, width))
category_index = 0
tile_index = 0for col in range(width):
for row in range(height):
tile_index += 1
if tile_index > sum(tiles_per_category[0:category_index]):
category_index += 1
waffle[row, col] = category_index
8. Choose a colormap and use matshow to display the matrix
fig = plt.figure()
colormap = plt.cm.coolwarm
plt.matshow(waffle, cmap=colormap)
plt.colorbar()

9. Add some beautifying element such as ticks and grid
fig = plt.figure()
colormap = plt.cm.coolwarm
plt.matshow(waffle, cmap=colormap)
ax = plt.gca()ax.set_xticks(np.arange(-0.5, (width), 1), minor=True)
ax.set_yticks(np.arange(-0.5, (height), 1), minor=True)ax.grid(which='minor', color='w', linestyle='-', linewidth=2)plt.xticks([])
plt.yticks([])
plt.colorbar()

10. Lastly, add legends that will complete the waffle chart. This is the complete code for the waffle chart. If you like it, you can simply keep this code and keep reusing it with your data.
fig = plt.figure()
colormap = plt.cm.coolwarm
plt.matshow(waffle, cmap=colormap)
ax = plt.gca()ax.set_xticks(np.arange(-0.5, (width), 1), minor=True)
ax.set_yticks(np.arange(-0.5, (height), 1), minor=True)ax.grid(which='minor', color='w', linestyle='-', linewidth=2)plt.xticks([])
plt.yticks([])values = df['number']
categories = df['country']
value_sign = ''
values_cumsum = np.cumsum(values)
total_values = values_cumsum[len(values_cumsum) - 1]legend_handles = []
for i, category in enumerate(categories):
if value_sign == '%':
label_str = category + ' (' + str(values[i]) + value_sign + ')'
else:
label_str = category + ' (' + value_sign + str(values[i]) + ')'
color_val = colormap(float(values_cumsum[i]) / total_values)
legend_handles.append(mpatches.Patch(color=color_val, label=label_str))
plt.legend(handles=legend_handles, loc = ‘lower center’, ncol=len(categories),
bbox_to_anchor=(0., 0.2, 0.95, 0.1)) #positioning legends
plt.colorbar()

Develop Waffle Chart Using Waffle Class
You need to install the pywaffle package using this command
pip install pywaffle
Now import Waffle from pywaffle package
from pywaffle import Waffle
Using the same data as the previous example, make a waffle plot using the Waffle function
fig = plt.figure(
FigureClass=Waffle,
rows=10,
values=list(df.number/5),
labels=list(df.country),
figsize=(12, 8),
legend={'bbox_to_anchor': (0.5, 0.5)}
)

Follow this link to learn the details about the pywaffle package.
Thank you so much for reading this article. I hope this was helpful.
#matplotlib #python #DataVisualization #wafflecharts #DataScience