Un gráfico de circular packing representa cada grupo como un círculo cuya área es proporcional a su valor, y los círculos se agrupan sin solaparse. Cuando los datos son jerárquicos los círculos se anidan. La librería circlify calcula la posición y el tamaño de los círculos y matplotlib los dibuja. Los ejemplos muestran la población (en millones) por continente y país.
circlify
circlify.circlify recibe los valores y devuelve una lista de círculos con sus coordenadas y su radio. Dibuja cada uno con plt.Circle.
import circlify
import matplotlib.pyplot as plt
data = [{"id": "Asia", "datum": 4800}, {"id": "África", "datum": 1460},
{"id": "Europa", "datum": 745}, {"id": "America", "datum": 1040},
{"id": "Oceanía", "datum": 45}]
circles = circlify.circlify(data, show_enclosure = False)
fig, ax = plt.subplots()
ax.axis("off")
ax.set_xlim(-1, 1)
ax.set_ylim(-1, 1)
ax.set_aspect("equal")
for circle in circles:
x, y, r = circle
ax.add_patch(plt.Circle((x, y), r, alpha = 0.6, linewidth = 2, edgecolor = "white"))
# plt.show()

Cada círculo conserva los datos originales en circle.ex, por lo que puedes escribir el nombre de cada grupo en el centro de su círculo y usar un color diferente para cada uno.
import circlify
import matplotlib.pyplot as plt
data = [{"id": "Asia", "datum": 4800}, {"id": "África", "datum": 1460},
{"id": "Europa", "datum": 745}, {"id": "America", "datum": 1040},
{"id": "Oceanía", "datum": 45}]
circles = circlify.circlify(data, show_enclosure = False)
colors = plt.cm.Set2.colors
fig, ax = plt.subplots()
ax.axis("off")
ax.set_xlim(-1, 1)
ax.set_ylim(-1, 1)
ax.set_aspect("equal")
for circle, color in zip(circles, colors):
x, y, r = circle
ax.add_patch(plt.Circle((x, y), r, color = color))
ax.annotate(circle.ex["id"], (x, y), ha = "center", va = "center")
# plt.show()

Agrega una clave children a cada grupo para crear una jerarquía. Los círculos que se devuelven tienen un atributo level que indica la profundidad, que puedes usar para dar un estilo diferente a cada nivel.
import circlify
import matplotlib.pyplot as plt
data = [{"id": "Europa", "datum": 280, "children": [
{"id": "Alemania", "datum": 84}, {"id": "Francia", "datum": 68},
{"id": "Italia", "datum": 59}, {"id": "España", "datum": 48}, {"id": "Polonia", "datum": 37}]},
{"id": "Asia", "datum": 2950, "children": [
{"id": "India", "datum": 1430}, {"id": "China", "datum": 1410},
{"id": "Japón", "datum": 124}]},
{"id": "America", "datum": 760, "children": [
{"id": "EE. UU.", "datum": 335}, {"id": "Brasil", "datum": 216},
{"id": "México", "datum": 129}, {"id": "Canadá", "datum": 39}]}]
circles = circlify.circlify(data, show_enclosure = False)
fig, ax = plt.subplots()
ax.axis("off")
ax.set_xlim(-1, 1)
ax.set_ylim(-1, 1)
ax.set_aspect("equal")
for circle in circles:
x, y, r = circle
if circle.level == 1:
ax.add_patch(plt.Circle((x, y), r, color = "#A8DADC", alpha = 0.6))
ax.annotate(circle.ex["id"], (x, y + r * 0.85), ha = "center", fontsize = 10, weight = "bold")
else:
ax.add_patch(plt.Circle((x, y), r, color = "#457B9D"))
if r > 0.08:
ax.annotate(circle.ex["id"], (x, y), ha = "center", va = "center", color = "white", fontsize = 8)
# plt.show()

Consulta también cómo crear un treemap en matplotlib, que representa el mismo tipo de datos con rectángulos.
También te puede interesar