I'm interested in developing a custom sunburst plot in matplotlib for binary search trees (such as those used in genealogy). I'm trying to achieve the following:
As you can see, it is a sunburst chart (such as offered by Plotly) with a removed wedge.
Here's something to at least get you started. You can use matplotlib's pie
chart to make nested pie charts. You can also remove specific wedges as shown in https://stackoverflow.com/a/63881380/1862861. Using this information you could do:
from matplotlib import pyplot as plt
ninner = 2 # number of inner wedge
width = 0.15 # width of inner wedges
radius = 0.5 # radius of inner wedges
gap = 100 # size of missing wedge
ngap = 300 - gap # total size of filled wedges (missing gap will be 1/3 of total)
fig, ax = plt.subplots()
for i in range(8):
if i > 0:
# expand pie chart radius and shrink wedge width
width *= 0.85
radius += width
# create data
data = [gap]
data.extend([ngap / 2**(i+1)] * ninner)
colors = ["lightgrey"] * len(data) # for now they are all grey!
ninner *= 2
# create pie chart
wedges, _ = ax.pie(
data,
radius=radius,
colors=colors,
wedgeprops={"width": width, "edgecolor": "w", "linewidth": 0.25},
startangle=-150, # shift start angle
)
wedges[0].set_visible(False) # make gap invisible
fig.tight_layout()
fig.show()
which produces:
Obviously this doesn't give the colours, but it's a start.
Update
Here's a version with some added colours:
from matplotlib import pyplot as plt
import numpy as np
def get_colours(N):
# use the tab20c colour map and get an array of colours
# Note: the "16" in this is due to the 16 colours in the tab20c colour map
cmap = plt.colormaps["tab20c"]
cs = cmap(np.arange(16))
if N <= 16:
step = 16 // N
colours = np.array([cs[i] for i in range(0, 16, step)])
else:
s = N // 16
colours = np.array([cs[int(np.floor(i / s))] for i in range(N)])
return colours
ninner = 2 # number of inner wedge
width = 0.15 # width of inner wedges
radius = 0.5 # radius of inner wedges
gap = 100 # size of missing wedge
ngap = 300 - gap # total size of filled wedges (missing gap will be 1/3 of total)
fig, ax = plt.subplots()
for i in range(8):
if i > 0:
# expand pie chart radius and shrink wedge width
width *= 0.85
radius += width
# create data
data = [gap]
data.extend([ngap / 2**(i+1)] * ninner)
colours = np.array([[0.8, 0.8, 0.8, 1.0] for _ in range(len(data))]) # initialise as all grey
wcolours = get_colours(ninner)
# this part will depend on your data!
# let's colour fill all the inner wedges
if i < 5:
colours[1:] = wcolours
else:
# choose some values to fill in
nfill = int(np.sqrt(ninner))
if nfill > 0:
wfill = np.zeros(ninner)
wfill[np.random.choice(np.arange(ninner), nfill, replace=False)] = 1.0
cv = colours[1:]
cv[wfill.astype(bool)] = wcolours[wfill.astype(bool)]
ninner *= 2
# create pie chart
wedges, _ = ax.pie(
data,
radius=radius,
colors=colours,
wedgeprops={"width": width, "edgecolor": "w", "linewidth": 0.25},
startangle=-150, # shift start angle
)
wedges[0].set_visible(False) # make gap invisible
fig.tight_layout()
fig.show()
which produces: