Waffle Chart
A waffle chart uses a fixed grid to show proportions. A 10 by 10 grid is a good default because each cell represents one percent.
Data and Layout
import pydreamplet as dp
data = [130, 65, 108]
data.sort(reverse=True)
side = 300
side_count = 10
gutter = 5
total_cells = side_count**2
total = sum(data)
Convert each value to a number of cells.
proportions = [round(value / total * total_cells) for value in data]
cell_side = (side - (side_count + 1) * gutter) / side_count
Build a list that maps each cell index to a group.
cell_group_map = []
for group_index, count in enumerate(proportions):
cell_group_map.extend([group_index] * count)
if len(cell_group_map) < total_cells:
cell_group_map.extend([None] * (total_cells - len(cell_group_map)))
Cell Paths
Drawing one path per group is more compact than appending 100 separate rectangles.
paths = {index: "" for index in range(len(data))}
for index in range(total_cells):
column = index % side_count
row = index // side_count
x = gutter + column * (cell_side + gutter)
y = gutter + row * (cell_side + gutter)
group = cell_group_map[index]
if group is not None:
paths[group] += f"M {x} {y} h {cell_side} v {cell_side} h -{cell_side} Z "
Draw the Chart
svg = dp.SVG(side, side)
colors = ["#14b8a6", "#f59e0b", "#6366f1"]
for group_index, path_data in paths.items():
if path_data:
svg.append(dp.Path(d=path_data, fill=colors[group_index]))
svg.save("waffle-chart.svg")