简体   繁体   中英

Controlling legend across multiple subplots with windrose axes

I cannot figure out how to make the legends not overlap with my figures (see below figure) in subplots. The problem is my axes are complicated because they are from a windrose. To get the axes:

1) I have downloaded the windrose.py from https://github.com/akrherz/windrose/tree/darylchanges

2) I copied the windrose.py into the same path with my python script, example.py

3) I changed windrose.py so that it is able to do subplots, according to the steps from Subplot of Windrose in matplotlib . Those steps were to make WindroseAxes as a projection into matplotlib. I edited the file windrose.py:

3a) Include an

import from matplotlib.projections import register_projection 

at the beginning of the file.

3b) Then add a name variable:

class WindroseAxes(PolarAxes):
    name = 'windrose'
    ...

3c) Finally, at the end of windrose.py, you add:

register_projection(WindroseAxes)

Once that is done, you can easily create your windrose axes using the projection argument to the matplotlib axes.

4) Now I ran my script below (example of my real script)

from windrose import WindroseAxes
import numpy as np
import matplotlib.pyplot as plt
from windrose_subplot import WindroseAxes

wind_speeds1 = np.array([12,10,13,15])
wind_dirs1 = np.array([60,76,32,80]) # in degrees

wind_speeds2 = np.array([23,12,10,8])
wind_dirs2 = np.array([23,45,29,13])

fig = plt.figure()
ax1 = fig.add_subplot(231,projection='windrose')
ax1.bar(wind_dirs1,wind_speeds1,normed=True,opening=0.8,edgecolor='white')
ax2 = fig.add_subplot(232,projection='windrose')
ax2.bar(wind_dirs2,wind_speeds2,normed=True,opening=0.8,edgecolor='white')

ax1.legend()
ax2.legend()
plt.tight_layout()
plt.show()

Ideally, I would like to create one legend with the max/min of all the subplots because they are all the same units. This legend will have to be the corresponding colors for each subplot for the same values across subplots (eg, a single normal legend relevant to all subplots). There will be 6 subplots in the real script but 2 here for now shows the point.

图例重叠

This is simple to fix. In order to only plot one legend, comment out or delete where you plot the first legend. In order to move the legend off of the plot, use bbox_to_anchor=() with some logical location. See below for an example that works for this example.

import numpy as np
import matplotlib.pyplot as plt
from windrose_subplot import WindroseAxes

wind_speeds1 = np.array([12,10,13,15])
wind_dirs1 = np.array([60,76,32,80]) # in degrees

wind_speeds2 = np.array([23,12,10,8])
wind_dirs2 = np.array([23,45,29,13])

fig = plt.figure()
ax1 = fig.add_subplot(231,projection='windrose')
ax1.bar(wind_dirs1,wind_speeds1,normed=True,opening=0.8,edgecolor='white')
ax2 = fig.add_subplot(232,projection='windrose')
ax2.bar(wind_dirs2,wind_speeds2,normed=True,opening=0.8,edgecolor='white')

# ax1.legend()
ax2.legend(bbox_to_anchor=(1.2 , -0.1))
plt.tight_layout()
plt.show()

在此处输入图片说明

However, note the bbox_to_anchor is reliant on the axis that the legend comes from, so

ax1.legend(bbox_to_anchor=1.2, -0.1))
#ax2.legend()

would display the legend underneath the second axis:

在此处输入图片说明

Thank you Hazard11, I found your answer very useful:) There is an issue with the answer though is the legend does not represent the first subplot because the bins are generated when creating the second subplot.

I just solved this issue by calculating the bins using numpy.histogram first and then passing that to windrose.WindroseAxes.bar() when creating each wind rose. Doing it this way means you need to pick which one you want to use to generate the bins. Another way to do it would be to define the bins manually or to create a function which generates some efficient binning for both which could then be used.

wind_speeds1 = np.array([12,10,13,15])
wind_dirs1 = np.array([60,76,32,80]) # in degrees

wind_speeds2 = np.array([23,12,10,8])
wind_dirs2 = np.array([23,45,29,13])

wind_speeds_bins = np.histogram(wind_speeds2, 5)[1]

fig = plt.figure()
ax1 = fig.add_subplot(231, projection='windrose')
ax1.bar(wind_dirs1 ,wind_speeds1, normed=True, opening=0.8, edgecolor='white', bins=wind_speeds_bins)
ax2 = fig.add_subplot(232, projection='windrose')
ax2.bar(wind_dirs2, wind_speeds2, normed=True, opening=0.8, edgecolor='white', bins=wind_speeds_bins)

# ax1.legend()
ax2.legend(bbox_to_anchor=(1.2 , -0.1))
plt.tight_layout()
plt.show()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM