PyWaffle is an open source, MIT-licensed Python package for plotting waffle charts.
It provides a Figure constructor class Waffle
, which could be passed to matplotlib.pyplot.figure and generates a matplotlib Figure object.
PyPI Page: https://pypi.org/project/pywaffle/
Documentation: http://pywaffle.readthedocs.io/
pip install pywaffle
import matplotlib.pyplot as plt
from pywaffle import Waffle
fig = plt.figure(
FigureClass=Waffle,
rows=5,
columns=10,
values=[48, 46, 6],
figsize=(5, 3)
)
plt.show()
The values are automatically scaled to 24, 23 and 3 to fit 5 * 10 chart size.
FigureClass
and figsize
are parameters of matplotlib.pyplot.figure
, you may find the full parameter list on matplotlib.pyplot.figure function reference.
Other parameters, including rows
, columns
, and values
in this example, are from Waffle
, and see PyWaffle's API Reference for details.
data = {'Cat1': 10, 'Cat2': 7, 'Cat3': 9}
fig = plt.figure(
FigureClass=Waffle,
rows=5,
values=data,
legend={'loc': 'upper left', 'bbox_to_anchor': (1.05, 1)},
)
plt.show()
In this example, only rows
is specified and columns
is empty, absolute values in values
are used as block numbers. Similarly, rows
could also be optional if columns
is specified.
If values
is a dict, the keys will be used as labels in the legend.
data = {'Car': 58, 'Pickup': 21, 'Truck': 11, 'Motorcycle': 7}
fig = plt.figure(
FigureClass=Waffle,
rows=5,
values=data,
colors=["#C1D82F", "#00A4E4", "#FBB034", '#6A737B'],
title={'label': 'Vehicle Sales by Vehicle Type', 'loc': 'left'},
labels=[f"{k} ({v}%)" for k, v in data.items()],
legend={'loc': 'lower left', 'bbox_to_anchor': (0, -0.4), 'ncol': len(data), 'framealpha': 0},
starting_location='NW',
vertical=True,
block_arranging_style='snake'
)
fig.set_facecolor('#EEEEEE')
plt.show()
Parameter colors
allows you to change the block color, and it accepts a list of colors that matplotlib can recognize, including hex, RGB in tuple, single character notation, etc. See Matplotlib Colors for details.
Parameter title
and legend
accept the same parameters as in Matplotlib, matplotlib.pyplot.title and matplotlib.pyplot.legend.
Parameter starting_location
, vertical
, and block_arranging_style
controls Where to Start First Block, Plotting Direction, and Where to Start Each Category.
You may find more details under Examples section in PyWaffle Documentation.
data = {'Car': 58, 'Pickup': 21, 'Truck': 11, 'Motorcycle': 7}
fig = plt.figure(
FigureClass=Waffle,
rows=5,
values=data,
colors=["#c1d82f", "#00a4e4", "#fbb034", '#6a737b'],
legend={'loc': 'upper left', 'bbox_to_anchor': (1, 1)},
icons=['car-side', 'truck-pickup', 'truck', 'motorcycle'],
font_size=12,
icon_legend=True
)
plt.show()
PyWaffle supports Font Awesome icons in the chart. See Plot with Characters or Icons for details.
fig = plt.figure()
ax = fig.add_subplot(111)
# Modify existed axis
ax.set_title("Axis Title")
ax.set_aspect(aspect="equal")
Waffle.make_waffle(
ax=ax, # pass axis to make_waffle
rows=5,
columns=10,
values=[30, 16, 4],
title={"label": "Waffle Title", "loc": "left"}
)
import pandas as pd
data = pd.DataFrame(
{
'labels': ['Car', 'Truck', 'Motorcycle'],
'Factory A': [32384, 13354, 5245],
'Factory B': [22147, 6678, 2156],
'Factory C': [8932, 3879, 896],
},
).set_index('labels')
# A glance of the data:
# Factory A Factory B Factory C
# labels
# Car 27384 22147 8932
# Truck 7354 6678 3879
# Motorcycle 3245 2156 1196
fig = plt.figure(
FigureClass=Waffle,
plots={
311: {
'values': data['Factory A'] / 1000, # Convert actual number to a reasonable block number
'labels': [f"{k} ({v})" for k, v in data['Factory A'].items()],
'legend': {'loc': 'upper left', 'bbox_to_anchor': (1.05, 1), 'fontsize': 8},
'title': {'label': 'Vehicle Production of Factory A', 'loc': 'left', 'fontsize': 12}
},
312: {
'values': data['Factory B'] / 1000,
'labels': [f"{k} ({v})" for k, v in data['Factory B'].items()],
'legend': {'loc': 'upper left', 'bbox_to_anchor': (1.2, 1), 'fontsize': 8},
'title': {'label': 'Vehicle Production of Factory B', 'loc': 'left', 'fontsize': 12}
},
313: {
'values': data['Factory C'] / 1000,
'labels': [f"{k} ({v})" for k, v in data['Factory C'].items()],
'legend': {'loc': 'upper left', 'bbox_to_anchor': (1.3, 1), 'fontsize': 8},
'title': {'label': 'Vehicle Production of Factory C', 'loc': 'left', 'fontsize': 12}
},
},
rows=5, # Outside parameter applied to all subplots, same as below
cmap_name="Accent", # Change color with cmap
rounding_rule='ceil', # Change rounding rule, so value less than 1000 will still have at least 1 block
figsize=(6, 5)
)
fig.suptitle('Vehicle Production by Vehicle Type', fontsize=14, fontweight='bold')
fig.supxlabel('1 block = 1000 vehicles', fontsize=8, x=0.14)
fig.set_facecolor('#EEEDE7')
plt.show()
Wanna try it yourself? There is Online Demo!
See CHANGELOG
LICENSE
file for the details.