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
.
How do I put those flag pictures in the graph (if it is even possbile)? And secondly, how can I automate this?
Our steps will be: Iterate over the bars. Get the x-axis position(x) and the width(w) of the bar this will help us to get the x coordinate of the text i.e. get_x()+get_width()/2. The y-coordinate(y) of the text can be found using the height of the bar i.e. get_height()
To add annotation, we first need to make grouped barplot before and then use Matplotlib's annotate function to add text for bars in grouped barplot. The “patches” attribute in Seaborn/Matplotlib object gives us access to each bar in barplot.
To annotate bars in barplot made with Seaborn, we will use Matplotlib's annotate function. Matplotlib's annotate() function is pretty versatile and we can customize various aspects of annotation in a plot.
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:
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
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.
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:
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()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With