Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
270 views
in Technique[技术] by (71.8m points)

python - Add image annotations to bar plots

So, for example, let's say I have some data

countries = ["Norway", "Spain", "Germany", "Canada", "China"]
valuesA = [20, 15, 30, 5, 26]
valuesB = [1, 5, 3, 6, 2] 

and I do wanna plot them like

this.

How do I put those flag pictures in the graph (if it is even possbile)? And secondly, how can I automate this?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

This solution will work for axes level plots produced with matplotlib, seaborn, and pandas.DataFrame.plot.

The main idea would be to separate the problem into small pieces:

  1. Get the flag as an array into the script. E.g.

     def get_flag(name):
         path = "path/to/flag/{}.png".format(name)
         im = plt.imread(path)
         return im
    
  2. Position an image at a certain position in a plot. This can be accomplished using an OffsetImage. An example can be found on the matplotlib page. Best use a function which takes the name of the country and the position as arguments and generates an AnnotationBbox with the OffsetImage inside.

  3. Drawing the barplot using ax.bar. To set the country names as ticklabels, use ax.set_ticklabels(countries). Then for every country place the OffsetImage from above using a loop.

(coord, 0) and xybox=(0., -16.) can be adjusted to place the image annotations at any location.

The final result may then look something like this:

enter image description here

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.offsetbox import OffsetImage,AnnotationBbox

def get_flag(name):
    path = "data/flags/Flags/flags/flags/24/{}.png".format(name.title())
    im = plt.imread(path)
    return im

def offset_image(coord, name, ax):
    img = get_flag(name)
    im = OffsetImage(img, zoom=0.72)
    im.image.axes = ax

    ab = AnnotationBbox(im, (coord, 0),  xybox=(0., -16.), frameon=False,
                        xycoords='data',  boxcoords="offset points", pad=0)

    ax.add_artist(ab)
    

countries = ["Norway", "Spain", "Germany", "Canada", "China"]
valuesA = [20, 15, 30, 5, 26]
 

fig, ax = plt.subplots()

ax.bar(range(len(countries)), valuesA, width=0.5,align="center")
ax.set_xticks(range(len(countries)))
ax.set_xticklabels(countries)
ax.tick_params(axis='x', which='major', pad=26)

for i, c in enumerate(countries):
    offset_image(i, c, ax)

plt.show()

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...