Home > other >  chart_pie index to generate
chart_pie index to generate

Time:12-29

I need help to generate this graph, especially with domains limits enter image description here

and the arrow indicating the domain enter image description here

all I can do is generate the domains name but not the limits and arrow

CodePudding user response:

The following code will produce something like what you require:

from matplotlib import pyplot as plt
from matplotlib.patches import Wedge
import numpy as np

labels = ["Obésité\nmassive", "Obésité", "Surpoids", "Normal", "Maigreur"]
innerlabels = [">40", "30 à 40", "25 à 30", "18,5 à 25", "< 18,5"]
colours = ["red", "darkorange", "orange", "green", "blue"]

fig, ax = plt.subplots(figsize=(6, 6), dpi=200)

theta = 0
dtheta = 180 / len(labels)
width = 0.35

def pol2cart(rho, phi):
    x = rho * np.cos(phi)
    y = rho * np.sin(phi)
    return(x, y)

patches = []
for i in range(len(labels)):
    # outer wedge
    wedge = Wedge(0, r=1, width=width, theta1=theta, theta2=(theta   dtheta), fc=colours[i], alpha=0.6, edgecolor="whitesmoke")
    ax.add_patch(wedge)

    # inner wedge
    wedge = Wedge(0, r=1 - width, width=width, theta1=theta, theta2=(theta   dtheta), fc=colours[i], edgecolor="whitesmoke")
    ax.add_patch(wedge)

    theta  = dtheta

    # add text label
    tr = 1 - (width / 2)
    ta = theta - dtheta / 2
    x, y = pol2cart(tr, np.deg2rad(ta))
    textangle = -np.fmod(90 - ta, 180)
    ax.text(x, y, labels[i], rotation=textangle, va="center", ha="center", color="white", fontweight="bold")

    # inner labels
    tr = (1 - width) - (width / 2)
    x, y = pol2cart(tr, np.deg2rad(ta))
    textangle = -np.fmod(90 - ta, 180)
    ax.text(x, y, innerlabels[i], rotation=textangle, va="center", ha="center", color="white")


ax.set_xlim([-1, 1])
ax.set_ylim([0, 1])
ax.set_axis_off()
ax.set_aspect("equal")


def bmiposition(bmi):
    """
    Get angular position of BMI arrow.
    """

    from scipy.interpolate import interp1d

    bmiranges = [(0, 18.5), (18.5, 25), (25, 30), (30, 40), (40, 80)]
    angrange = [(180 - dtheta * i, 180 - dtheta * (i   1)) for i in range(len(bmiranges))]

    interpfuncs = []
    for i in range(len(bmiranges)):
        interpfuncs.append(interp1d(bmiranges[i], angrange[i], kind="linear"))

    bmiang = np.piecewise(
        bmi,
        [bmiranges[i][0] < bmi <= bmiranges[i][1] for i in range(len(bmiranges))],
        interpfuncs,
    )

    return bmiang


bmi = 22.5  # set BMI

# add arrow
pos = bmiposition(bmi)  # get BMI angle
x, y = pol2cart(0.25, np.deg2rad(pos))
ax.arrow(0, 0, x, y, head_length=0.125, width=0.025, fc="k")
ax.plot(0, 0, 'ko', ms=10)  # circle at origin

giving:

enter image description here

  • Related