使用 matplotlib 代理艺术家将图例添加到平行坐标图
Adding legend to parallel coordinated plot using matplotlib proxy artist
我很难将图例添加到 matplotlib.pyplot
,我的目标是使平行坐标图类似于
Parallel Coordinates plot in Matplotlib
由于我的用例相似,所以我使用了提供的解决方案,只是我只有 2 个观察值,每组 1 个,我添加了
plt.legend(axes,style)
,因此创建了图例,但是当我 运行 代码时,我收到以下警告并且没有图例。
:\Python27\lib\site-packages\matplotlib\legend.py:634: UserWarning: Legend does not support instances.
A proxy artist may be used instead.
See: http://matplotlib.org/users/legend_guide.html#using-proxy-artist
"#using-proxy-artist".format(orig_handle)
我尝试查看文档但找不到解决方案。
我发现下面列出了另一个 Whosebug post,但仍然不太清楚图例的用法,尤其是在传递给图例函数之前如何解压缩子图。谁能解释一下它是如何工作的。
#!/usr/bin/python
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
def parallel_coordinates(data_sets, style=None):
dims = len(data_sets[0])
x = range(dims)
fig, axes = plt.subplots(1, dims-1, sharey=False)
if style is None:
style = ['r-']*len(data_sets)
# Calculate the limits on the data
min_max_range = list()
for m in zip(*data_sets):
mn = min(m)
mx = max(m)
if mn == mx:
mn -= 0.5
mx = mn + 1.
r = float(mx - mn)
min_max_range.append((mn, mx, r))
# Normalize the data sets
norm_data_sets = list()
for ds in data_sets:
nds = [(value - min_max_range[dimension][0]) /
min_max_range[dimension][2]
for dimension,value in enumerate(ds)]
norm_data_sets.append(nds)
data_sets = norm_data_sets
# Plot the datasets on all the subplots
for i, ax in enumerate(axes):
for dsi, d in enumerate(data_sets):
ax.plot(x, d, style[dsi])
ax.set_xlim([x[i], x[i+1]])
# Set the x axis ticks
for dimension, (axx,xx) in enumerate(zip(axes, x[:-1])):
axx.xaxis.set_major_locator(ticker.FixedLocator([xx]))
ticks = len(axx.get_yticklabels())
labels = list()
step = min_max_range[dimension][2] / (ticks - 1)
mn = min_max_range[dimension][0]
for i in xrange(ticks):
v = mn + i*step
labels.append('%4.2f' % v)
axx.set_yticklabels(labels)
# Move the final axis' ticks to the right-hand side
axx = plt.twinx(axes[-1])
dimension += 1
axx.xaxis.set_major_locator(ticker.FixedLocator([x[-2], x[-1]]))
ticks = len(axx.get_yticklabels())
step = min_max_range[dimension][2] / (ticks - 1)
mn = min_max_range[dimension][0]
labels = ['%4.2f' % (mn + i*step) for i in xrange(ticks)]
axx.set_yticklabels(labels)
# Stack the subplots
plt.subplots_adjust(wspace=0)
plt.legend(axes,style)
return plt
if __name__ == '__main__':
import random
base = [0, 0, 5, 5, 0]
scale = [1.5, 2., 1.0, 2., 2.]
data = [[base[x] + random.uniform(0., 1.)*scale[x]
for x in xrange(5)] for y in xrange(1)]
colors = ['r'] * 1
base = [3, 6, 0, 1, 3]
scale = [1.5, 2., 2.5, 2., 2.]
data.extend([[base[x] + random.uniform(0., 1.)*scale[x]
for x in xrange(5)] for y in xrange(1)])
colors.extend(['b'] * 1)
parallel_coordinates(data, style=colors).show()
错误基本上是因为 matplotlib
不支持程序生成图例,并且告诉您必须手动生成图例。例如
blue_line = mlines.Line2D([], [], color='blue', label='Blue')
red_line = mlines.Line2D([], [], color='red', label='Red')
plt.legend(handles=[blue_line, red_line])
这依赖于将 matplotlib.lines
导入为 mlines
。在相关代码中,这将生成
如果您更喜欢补丁而不是线条,也可以使用 matplotlib.patches
,即
blue_patch = mpatches.Patch(color='blue', label='Blue')
red_patch = mpatches.Patch(color='red', label='Red')
plt.legend(handles=[blue_patch, red_patch])
依赖于将 matplotlib.patches
导入为 mpatches
。这会生成
您可以在图例中添加您需要的任何自定义 handles
- 混合色块、线条和标记是可以接受的。
我很难将图例添加到 matplotlib.pyplot
,我的目标是使平行坐标图类似于
Parallel Coordinates plot in Matplotlib
由于我的用例相似,所以我使用了提供的解决方案,只是我只有 2 个观察值,每组 1 个,我添加了
plt.legend(axes,style)
,因此创建了图例,但是当我 运行 代码时,我收到以下警告并且没有图例。
:\Python27\lib\site-packages\matplotlib\legend.py:634: UserWarning: Legend does not support instances. A proxy artist may be used instead. See: http://matplotlib.org/users/legend_guide.html#using-proxy-artist "#using-proxy-artist".format(orig_handle)
我尝试查看文档但找不到解决方案。
我发现下面列出了另一个 Whosebug post,但仍然不太清楚图例的用法,尤其是在传递给图例函数之前如何解压缩子图。谁能解释一下它是如何工作的。
#!/usr/bin/python
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
def parallel_coordinates(data_sets, style=None):
dims = len(data_sets[0])
x = range(dims)
fig, axes = plt.subplots(1, dims-1, sharey=False)
if style is None:
style = ['r-']*len(data_sets)
# Calculate the limits on the data
min_max_range = list()
for m in zip(*data_sets):
mn = min(m)
mx = max(m)
if mn == mx:
mn -= 0.5
mx = mn + 1.
r = float(mx - mn)
min_max_range.append((mn, mx, r))
# Normalize the data sets
norm_data_sets = list()
for ds in data_sets:
nds = [(value - min_max_range[dimension][0]) /
min_max_range[dimension][2]
for dimension,value in enumerate(ds)]
norm_data_sets.append(nds)
data_sets = norm_data_sets
# Plot the datasets on all the subplots
for i, ax in enumerate(axes):
for dsi, d in enumerate(data_sets):
ax.plot(x, d, style[dsi])
ax.set_xlim([x[i], x[i+1]])
# Set the x axis ticks
for dimension, (axx,xx) in enumerate(zip(axes, x[:-1])):
axx.xaxis.set_major_locator(ticker.FixedLocator([xx]))
ticks = len(axx.get_yticklabels())
labels = list()
step = min_max_range[dimension][2] / (ticks - 1)
mn = min_max_range[dimension][0]
for i in xrange(ticks):
v = mn + i*step
labels.append('%4.2f' % v)
axx.set_yticklabels(labels)
# Move the final axis' ticks to the right-hand side
axx = plt.twinx(axes[-1])
dimension += 1
axx.xaxis.set_major_locator(ticker.FixedLocator([x[-2], x[-1]]))
ticks = len(axx.get_yticklabels())
step = min_max_range[dimension][2] / (ticks - 1)
mn = min_max_range[dimension][0]
labels = ['%4.2f' % (mn + i*step) for i in xrange(ticks)]
axx.set_yticklabels(labels)
# Stack the subplots
plt.subplots_adjust(wspace=0)
plt.legend(axes,style)
return plt
if __name__ == '__main__':
import random
base = [0, 0, 5, 5, 0]
scale = [1.5, 2., 1.0, 2., 2.]
data = [[base[x] + random.uniform(0., 1.)*scale[x]
for x in xrange(5)] for y in xrange(1)]
colors = ['r'] * 1
base = [3, 6, 0, 1, 3]
scale = [1.5, 2., 2.5, 2., 2.]
data.extend([[base[x] + random.uniform(0., 1.)*scale[x]
for x in xrange(5)] for y in xrange(1)])
colors.extend(['b'] * 1)
parallel_coordinates(data, style=colors).show()
错误基本上是因为 matplotlib
不支持程序生成图例,并且告诉您必须手动生成图例。例如
blue_line = mlines.Line2D([], [], color='blue', label='Blue')
red_line = mlines.Line2D([], [], color='red', label='Red')
plt.legend(handles=[blue_line, red_line])
这依赖于将 matplotlib.lines
导入为 mlines
。在相关代码中,这将生成
如果您更喜欢补丁而不是线条,也可以使用 matplotlib.patches
,即
blue_patch = mpatches.Patch(color='blue', label='Blue')
red_patch = mpatches.Patch(color='red', label='Red')
plt.legend(handles=[blue_patch, red_patch])
依赖于将 matplotlib.patches
导入为 mpatches
。这会生成
您可以在图例中添加您需要的任何自定义 handles
- 混合色块、线条和标记是可以接受的。