我想复制here所描述的雷达图
主要区别是我的数据有两个不同的spoke_labels
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Circle, RegularPolygon
from matplotlib.path import Path
from matplotlib.projections.polar import PolarAxes
from matplotlib.projections import register_projection
from matplotlib.spines import Spine
from matplotlib.transforms import Affine2D
def radar_factory(num_vars, frame='circle'):
"""
Create a radar chart with `num_vars` axes.
This function creates a RadarAxes projection and registers it.
Parameters
----------
num_vars : int
Number of variables for radar chart.
frame : {'circle', 'polygon'}
Shape of frame surrounding axes.
"""
# calculate evenly-spaced axis angles
theta = np.linspace(0, 2*np.pi, num_vars, endpoint=False)
class RadarTransform(PolarAxes.PolarTransform):
def transform_path_non_affine(self, path):
# Paths with non-unit interpolation steps correspond to gridlines,
# in which case we force interpolation (to defeat PolarTransform's
# autoconversion to circular arcs).
if path._interpolation_steps > 1:
path = path.interpolated(num_vars)
return Path(self.transform(path.vertices), path.codes)
class RadarAxes(PolarAxes):
name = 'radar'
PolarTransform = RadarTransform
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# rotate plot such that the first axis is at the top
self.set_theta_zero_location('N')
def fill(self, *args, closed=True, **kwargs):
"""Override fill so that line is closed by default"""
return super().fill(closed=closed, *args, **kwargs)
def plot(self, *args, **kwargs):
"""Override plot so that line is closed by default"""
lines = super().plot(*args, **kwargs)
for line in lines:
self._close_line(line)
def _close_line(self, line):
x, y = line.get_data()
# FIXME: markers at x[0], y[0] get doubled-up
if x[0] != x[-1]:
x = np.append(x, x[0])
y = np.append(y, y[0])
line.set_data(x, y)
def set_varlabels(self, labels):
self.set_thetagrids(np.degrees(theta), labels)
def _gen_axes_patch(self):
# The Axes patch must be centered at (0.5, 0.5) and of radius 0.5
# in axes coordinates.
if frame == 'circle':
return Circle((0.5, 0.5), 0.5)
elif frame == 'polygon':
return RegularPolygon((0.5, 0.5), num_vars,
radius=.5, edgecolor="k")
else:
raise ValueError("Unknown value for 'frame': %s" % frame)
def _gen_axes_spines(self):
if frame == 'circle':
return super()._gen_axes_spines()
elif frame == 'polygon':
# spine_type must be 'left'/'right'/'top'/'bottom'/'circle'.
spine = Spine(axes=self,
spine_type='circle',
path=Path.unit_regular_polygon(num_vars))
# unit_regular_polygon gives a polygon of radius 1 centered at
# (0, 0) but we want a polygon of radius 0.5 centered at (0.5,
# 0.5) in axes coordinates.
spine.set_transform(Affine2D().scale(.5).translate(.5, .5)
+ self.transAxes)
return {'polar': spine}
else:
raise ValueError("Unknown value for 'frame': %s" % frame)
register_projection(RadarAxes)
return theta
def example_data():
data = [
['WW yield', 'WR yield', 'WB yield', 'SM yield','N leached','Net N minerilization',
'Emitted soil $N_{2}$O','Organic soil N','Organic soil C','Emitted soil $CO_{2}$'],
('WW-WR-WB-SM', [
[0.629053747,0.254076315,0.332256277,0.204105265,0.133944624,0.318652711,0.075673605,0.207815416,0.268688223,
0.355527198],
[0.638266936,0.256631724,0.34185792,0.212581768,0.120456481,0.335636918,0.075777949,0.2048961,0.265332129,
0.363333365],
[0.6216949,0.261880304,0.373231106,0.458953575,0.099304806,0.389855072,0.060179553,0.376827867,0.411683333,
0.4480729]]),
['WR yield', 'WB yield', 'WW yield', 'SP yield','N leached','Net N minerilization',
'Emitted soil N$_{2}$O','Organic soil N','Organic soil C','Emitted soil $CO_{2}$'], **#here I have different label**
('WR-WB-WW-SP', [
[0.303873044,0.343198048,0.72326815,0.470654888,0.147377613,0.349091327,0.087892159,0.215422083,0.273716559,
0.357139508],
[0.344731808,0.336010854,0.714918073,0.52981827,0.102251601,0.378815911,0.062455782,0.205903907,0.265096764,
0.377555353],
[0.329971424,0.380316019,0.809793741,0.59992031,0.110443314,0.457303888,0.08134116,0.413050845,0.435613362,
0.472325334]])
]
return data
if __name__ == '__main__':
N = 10
theta = radar_factory(N, frame='polygon')
data = example_data()
spoke_labels = data.pop(0)
fig, axs = plt.subplots(figsize=(20, 20), nrows=2, ncols=1,
subplot_kw=dict(projection='radar'))
labels = ('Factor 1', 'Factor 2', 'Factor 3')
num_vars = len(labels)
colors = ['b', 'r', 'g']
# Plot the two cases from the example data on separate axes
for ax, (title, case_data) in zip(axs.flat, data):
#ax.set_rgrids([0.2, 0.4, 0.6, 0.8],angle=360)
ax.set_title(title, weight='bold', size='medium', position=(0.5, 1.1),
horizontalalignment='center', verticalalignment='center')
for d, color in zip(case_data, colors):
ax.plot(theta, d,'--', color=color)
ax.set_varlabels(spoke_labels)
ax.set_rgrids([0,0.1, 0.2, 0.3, 0.4, 0.5,0.6,0.7,0.8],angle=90)
ax.grid(color='silver',linestyle='-', linewidth=0.5,dash_capstyle='projecting',ds='default')
ax.spines['polar'].set_visible(False)
ax.set_rlabel_position(90 / num_vars)
ax.legend(['Factor 1', 'Factor 2', 'Factor 3'],bbox_to_anchor=(1.1, 1.05),loc='best',frameon=False)
plt.show()
这个错误是因为zip(axs.flat,data)接收到太多的值而无法解包。如何解决?应该将每种情况的数据分开并在两个轴上绘图。如果是这样的话,欣赏任何相关的例子…
[![~\AppData\Local\Temp\ipykernel_17292\4071153916.py in <module>
157 colors = \['b', 'r', 'g'\]
158 # Plot the four cases from the example data on separate axes
--> 159 for ax, (title, case_data) in zip(axs.flat, data):
160 #ax.set_rgrids(\[0.2, 0.4, 0.6, 0.8\],angle=360)
161 ax.set_title(title, weight='bold', size='medium', position=(0.5, 1.1),
ValueError: too many values to unpack (expected 2)][2]][2]
1条答案
按热度按时间ryevplcw1#
除了上面评论中的解决方案,我是这样做的