RémyClaverie
RémyClaverie

Reputation: 47

matplotlib image as labels on pie chart

I don't find the way to move the labels' text to images. How to use PIL or imageio to retrieve flag images from internet and use them instead of the strings. Here is the MWE:

import matplotlib.pyplot as plt

nationalities = {
    'Fr': 5,
    'De': 10,
    'It': 3,
    'Se': 5,
    'Pl':2,
    'Cz': 3,
}

flags = {
    'Fr':'https://www.touteleurope.eu/wp-content/uploads/2022/08/drapeau-France.png',
    'De':'https://www.touteleurope.eu/wp-content/uploads/2022/07/drapeau-allemagne.png',
    'It':'https://www.touteleurope.eu/wp-content/uploads/2022/08/drapeau-Italie.png',
    'Se':'https://www.touteleurope.eu/wp-content/uploads/2022/07/1280px-Flag_of_Sweden.svg.png',
    'Pl':'https://www.touteleurope.eu/wp-content/uploads/2022/08/drapeau-Pologne.png',
    'Cz':'https://www.touteleurope.eu/wp-content/uploads/2022/08/drapeau-Republique-tcheque.png',
}

fig, ax = plt.subplots(figsize=(18,6))
plt.xticks(fontsize=20)
plt.yticks([], fontsize=20)
Countries = []
Composers = []
Flags = []
for Cnty, Cps in nationalities.items():
    Countries.append(Cnty)
    Composers.append(Cps)
    Flags.append( flags[Cnty] ) 
    nb_of_composers = 100*max(Composers)/sum(Composers)
print (str(nb_of_composers)[0:2])
#plt.pie( Composers, labels=Flags, radius=1, textprops={'size': 20}, wedgeprops={'linewidth': 1.0, 'edgecolor': 'white'}, )
plt.pie( Composers, labels=Countries, radius=1, textprops={'size': 20}, wedgeprops={'linewidth': 1.0, 'edgecolor': 'white'}, )
plt.text(s=str(nb_of_composers)[0:2]+'%', x=-0.7, y=0.3, fontsize=30, color='white')
plt.tight_layout()
plt.show()

Thanks a lot for your help !

Upvotes: 2

Views: 26

Answers (1)

mozway
mozway

Reputation: 262214

You can download the images with request+PIL, then add the images with imshow:

from PIL import Image
import requests

# download the images
headers ={
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36'
}

Flags = {k: Image.open(requests.get(url, headers=headers, stream=True).raw)
         for k, url in flags.items()}

# plot the original graph
fig, ax = plt.subplots(figsize=(9,3))
plt.xticks(fontsize=20)
plt.yticks([], fontsize=20)

Countries, Composers = zip(*nationalities.items())
nb_of_composers = max(Composers)/sum(Composers)

patches, texts = plt.pie(Composers, labels=Countries, radius=1, textprops={'size': 20},
                         wedgeprops={'linewidth': 1.0, 'edgecolor': 'white'}, )
plt.text(s=f'{nb_of_composers:.0%}', x=-0.7, y=0.3, fontsize=30, color='white')

# replace the string labels with images
for t in texts:
    x, y = t.get_position()
    ax.imshow(Flags[t._text], extent=[x-0.15, x+0.15, y-0.1, y+0.1], zorder=1)
    t.set_visible(False)

plt.tight_layout()

Output:

matplotlib pie chart image label flags

Upvotes: 1

Related Questions