I have a map image, and I have a circular Seaborn bar plot. The map looks like this:
and the Seaborn plot looks like this:
How can I overlap the two, and offset the Seaborn plot on the map to match specific coordinates? For instance, I want something that looks like the following image, where the circular bar chart is offset on the image with known coordinates indicating a specific Lat,Lon location.
I've tried using code from this example:
img = plt.imread('map.jpg')
fig, ax = plt.subplots(figsize=(6, 6))
plt.style.use('dark_background')
sns.barplot(x='Provider', y='Var_diff', hue='Provider', data=one_stat, ax=ax,
palette='gist_rainbow', legend=False)
# Turn off surrounding circular frame
ax.set_frame_on(False)
# Turn off axis labels
ax.set(xlabel=None); ax.set(ylabel=None)
ax.set(xticks=[]); ax.set(yticks=[])
ax.imshow(img, extent=[-18, 18, -9, 9])
, but the same argument (subplot_kw=dict(polar=True)
) used to make the barplot circular in the figure and axis definition (e.g., fig, ax = plt.subplots(figsize=(6, 6), subplot_kw=dict(polar=True))
) curve the background image to match the circular bar plot:
and taking the argument out results in a purely rectangular plot:
Is there a way to define two different figures and axes and overlap them? Or how could I achieve the final result?
Solution
Using @Stef's response, my final plot command ended up being:
img = plt.imread('map.jpg')
fig, ax_bg = plt.subplots()
ax_bars = fig.add_axes(rect=(0.2, 0.2, 0.2, 0.2), polar=True)
plt.style.use('dark_background')
sns.barplot(x='Provider', y='Var_diff', hue='Provider',
data=one_stat, ax=ax_bars, palette='gist_rainbow', legend=False)
# Turn off surrounding circular frame
ax_bars.set_frame_on(False)
# Turn off axis labels
ax_bars.set(xlabel=None); ax_bars.set(ylabel=None)
ax_bars.set(xticks=[]); ax_bars.set(yticks=[])
ax_bg.imshow(img, extent=[-180, 180, -90, 90])
which produces
You can first create the axes for the background image and then create another axes for the polar bar chart on top of it. The only difficulty is to get the rect coords for the bars axes. If you don't want to use trial and error you can first transform from data to display coords ax_bg.transData.transform(...)
and then back to figure coords fig.transFigure.inverted().transform(...)
for the rect coords of the bars axes.
fig, ax_bg = plt.subplots()
ax_bars = fig.add_axes(rect=(0.7, 0.2, .2, .2), polar=True)
ax_bars.set_axis_off()
ax_bars.bar(range(4), [2, .1, 3, 4])