具有不同内容的子图的全球图例 [英] Global legend for subplots with different content
问题描述
我通读了以前的解决方案,但无法使它们起作用.我想为每个子图提供一个全球性的传说. 该子图的ax对象由预定义类中的预定义函数"get_plot"生成 "The_predefined_plotting_class"大致如下:
I read through previous solutions but couldn´t make any of them work. I want to have a global legend for individual subplots. The ax objects for this subplot are generated by a predefined function "get_plot" out of a predefined class "The_predefined_plotting_class" roughly like this:
该函数返回一个斧头对象,并且每个斧头对象在原始数据文件"的多个列中都有多个图".
the function returns an ax object and each ax objects has multiple "plots"/ from multiple columns of the original "datafiles".
在我在此站点上找到的一种解决方案中,我读到可以使用:
In one of the solutions i found on this site i read that i could use:
打造全球传奇.不幸的是,我不知道如何将单个斧头对象(或其中的数据)附加到句柄上以完成这项工作. 每个图都包含一些相同的列名,但有些不同.如果一个条目/名称存在于许多子图中,则只能打印一次.
to make a global legend. Unfortunately i have no idea how to append the individual ax objects ( or the data therein) to handles to make this work. Each plots contains some identical column names and some that differ. If an entry/name exists in many subplots it should only be printed once.
编辑
真的很抱歉我不得不使用图片,但是无论我在Web端做了什么,即使在预览窗口中正确显示了代码也无法发布我的代码(屏幕截图来自此窗口)
I am really sorry that i had to use pictures, but whatever i did the webside did not let me post my code even tho it was shown properly in the preview window ( the screenshots are from this window)
EDIT2
如果我这样做:
lines=[]
labels=[]
for idata, datafile in enumerate(datafiles):
MYData = The_predefined_plotting_class.from_file(datafile)
axis[idata] = The_predefined_plotting_class.get_plot( *kwargs)
h, l = axis[idata].get_legend_handles_labels()
lines.append(h)
labels.append(l)
LINES=[]
LABELS=[]
for i in range(0, nrows):
LINES+=lines[i]
LABELS+=labels[i]
plt.legend( LINES, LABELS, loc="upper left", bbox_to_anchor=[0, 1],ncol=3, shadow=True, title="Legend", fancybox=True)
plt.show()
然后显示所有数据.一些数据具有相同的行和标签处理程序.现在剩下的问题是遍历两个列表,并且如果在两个列表中的 tuple (LINES [j]; LABELS [j])=(LINES [i] ; LABELS [i])存在两次(并且只有那时).最好是第一个条目:
Then it shows all Data . Some of the Data has the same lines and labels handler. I am now left with the problem to iterate through both lists and delete only one entry if in both lists the tuple (LINES[j];LABELS[j]) = (LINES[i];LABELS[i]) exist twice (and only then). Preferably the first entry:
EDIT3
labels =[]
lines = []
h=["Cat","Mouse","Dog","Cat","Cat","Kangaroo","Dog"]
l=["black","white","brown","white","black","yellow","brown"]
for handle, label in zip(h, l):
if label not in labels :
lines.append(handle)
labels.append(label)
print "The disired Output is :"
print '["Cat","Mouse","Dog","Cat","Kangaroo"]'
print '["black","white","brown","white","yellow"]'
print "currently you get:"
print lines
print labels
EDIT4
我添加了一个最小"的工作示例,其中应包含真实数据中发生的所有可能情况.
I add a "minimum" working example which should contain all possible situations that occur in my real data.
lines=[]
labels=[]
legend_properties = {'weight':'bold','size':10}
# Example data
x1 = np.linspace(0.0, 5.0)
x2 = np.linspace(0.0, 2.0)
a = np.cos(2 * np.pi * x1) * np.exp(-x1)
b = np.cos(2 * np.pi * x2)
c = np.cos(5 * np.pi * x1) * np.exp(-x1)
c2 = np.cos(5 * np.pi * x1**2) * np.exp(-x1)
d = np.cos(2 * np.pi * x2 )
d2 = np.cos(2 * np.pi * x2-1 )
e = x1*5
e2 = -x1*5
f = np.exp(x1)-e
f2 = (np.exp(x1)-e)/2
nrows = 4
# Plot
fig, axis = plt.subplots(nrows, sharex=True, sharey=False, figsize=(5, 8))
fig.subplots_adjust(hspace=0.0001)
fig.suptitle("Stacked Plots with global Legend wich contains to little elements",fontsize=14,weight='bold')
axis[0].plot(x1, e, 'k--', label='Label1',color="green")
axis[0].plot(x1, e2, 'k--', label='Label2',color="blue")
axis[0].plot(x1, a, 'k--', label='Label3',color="yellow")
axis[1].plot(x1, c, 'k--', label='Label1',color="green")
axis[1].plot(x1, c2, 'k--', label='Label2',color="blue")
axis[1].plot(x1, a, 'k--', label='Label3',color="grey")
axis[2].plot(x2, d, '*', label='Label1',color="green")
axis[2].plot(x2, d2, 'D', label='Label2',color="green")
axis[3].plot(x1, f, 'H', label='Label1',color="green")
axis[3].plot(x1, f2, 'D', label='Label2',color="green")
for i in range(nrows):
h, l = axis[i].get_legend_handles_labels()
for handle, label in zip(h, l):
if label not in labels:
lines.append(handle)
labels.append(label)
# only 3 Legend entrys Label1 , Label2 and Label3 are visible .. Differences in cloors and markers are ignored
plt.legend(handles=lines, labels=labels,bbox_to_anchor=(0., nrows+.02, 1., .102), loc=3,ncol=3, prop=legend_properties,mode="expand", borderaxespad=0.,frameon=False,framealpha=0.0)
plt.show()
EDIT5
这是有问题的脚本的一部分,其中生成了实际图. 列"仅包含要绘制的实际数据的名称.
this is the part form the script in question where the actual plots are generated. "columns" contains just the names of the actual data to be ploted.
# add plots
ic = 0
for col in columns:
if col == "envelope":
ax.plot(self.data.index, self.data.envelope,
linewidth=LINEWIDTH_envelope, c=last_color, label="")
elif col == "Exp":
ax.plot(self.data.index, self.data.Exp, c=first_color, linestyle="",
label="Exp", marker="o", markersize=MARKERSIZE )
else:
color = used_colors[ic % len(used_colors)]
if fill and "BG" in self.data.columns:
ax.fill_between(self.data.index, self.data.BG,
self.data[col], label=col, alpha=ALPHA,
color=color)
else:
ax.plot(self.data.index, self.data[col], linewidth=LINEWIDTH,
c=color, label=col)
ic += 1
EDIT6
我试图根据我在这里提出的想法找到解决方案:
I tried to find a solution based on the idea i presented here:
不幸的是,这对于包含字符串的两个列表有效,似乎不适用于艺术家手部.
Unfortunately what works for two Lists containing strings does not work for the artist handels it seems.
import matplotlib.pyplot as plt
import numpy as np
LI=[]
lines=[]
labels=[]
legend_properties = {'weight':'bold','size':10}
# Example data
x1 = np.linspace(0.0, 5.0)
x2 = np.linspace(0.0, 2.0)
a = np.cos(2 * np.pi * x1) * np.exp(-x1)
b = np.cos(2 * np.pi * x2)
c = np.cos(5 * np.pi * x1) * np.exp(-x1)
c2 = np.cos(5 * np.pi * x1**2) * np.exp(-x1)
d = np.cos(2 * np.pi * x2 )
d2 = np.cos(2 * np.pi * x2-1 )
e = x1*5
e2 = -x1*5
f = np.exp(x1)-e
f2 = (np.exp(x1)-e)/2
nrows = 4
# Plot
fig, axis = plt.subplots(nrows, sharex=True, sharey=False, figsize=(5, 8))
fig.subplots_adjust(hspace=0.0001)
#fig.suptitle("Stacked Plots with global Legend wich contains to little elements",fontsize=14,weight='bold')
axis[0].plot(x1, e, 'k--', label='Label1',color="green")
axis[0].plot(x1, e2, 'k--', label='Label2',color="blue")
axis[0].plot(x1, a, 'k--', label='Label3',color="yellow")
axis[1].plot(x1, c, 'k--', label='Label1',color="green")
axis[1].plot(x1, c2, 'k--', label='Label2',color="blue")
axis[1].plot(x1, a, 'k--', label='Label3',color="grey")
axis[2].plot(x2, d, '*', label='Label1',color="green")
axis[2].plot(x2, d2, 'D', label='Label2',color="green")
axis[3].plot(x1, f, 'H', label='Label1',color="green")
axis[3].plot(x1, f2, 'D', label='Label2',color="green")
for i in range(nrows):
print i
h, l = axis[i].get_legend_handles_labels()
for hl in zip(h,l):
if hl not in LI:
LI.append(hl)
lines.append(LI[-1][0])
labels.append(LI[-1][1])
print LI
# only 3 Legend entrys Label1 , Label2 and Label3 are visible .. Differences in cloors and markers are ignored
plt.legend(handles=lines, labels=labels,bbox_to_anchor=(0., nrows+.02, 1., .102), loc=3,ncol=3, prop=legend_properties,mode="expand", borderaxespad=0.,frameon=False,framealpha=0.0)
plt.show()
我认为问题在于,仅对内存地址的字符串进行了比较
I think the problem is that only the string for the Memory adress is compared in
if hl not in LI:
不是"h"的实际内容?
not the actual content of "h"?
解决方案是根据对ImportanceOfBeingErnest的解释在相关帖子中给出的
solution based on the explanation of ImportanceOfBeingErnest gave in a related post Link7:
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.mlab as mlab
import math
import matplotlib.collections
def is_inlist(handle, handles):
for h in handles:
if isinstance(handle, matplotlib.collections.PolyCollection) and isinstance(h, matplotlib.collections.PolyCollection):
if np.all(h.get_facecolor() == handle.get_facecolor()) and \
np.all(h.get_linestyle() == handle.get_linestyle()) and \
np.all(h.get_alpha() == handle.get_alpha()):
return True
if isinstance(handle, matplotlib.lines.Line2D) and isinstance(h, matplotlib.lines.Line2D):
if h.get_color() == handle.get_color() and \
h.get_linestyle() == handle.get_linestyle() and \
h.get_marker() == handle.get_marker():
return True
return False
lines=[]
labels=[]
legend_properties = {'weight':'bold','size':10}
# Example data
mu = 0
mu2 = 5
variance = 1
variance2 = 2
sigma = math.sqrt(variance)
sigma2 = math.sqrt(variance2)
x = np.linspace(mu-3*variance,mu+3*variance, 100)
x2 = np.linspace(mu2-3*variance2,mu2+3*variance2, 100)
nrows = 4
# Plot
fig, axis = plt.subplots(nrows, sharex=True, sharey=False, figsize=(5, 8))
fig.subplots_adjust(hspace=0.0001)
#fig.suptitle("Stacked Plots with global Legend wich contains to little elements",fontsize=14,weight='bold')
axis[0].fill_between(x+6,0,mlab.normpdf(x, mu, sigma), color='green',alpha=0.5,label="PEAK1", interpolate=True)
axis[0].fill_between(x+4,0,mlab.normpdf(x, mu, sigma), color='orange',alpha=0.5,label="PEAK2", interpolate=True)
axis[0].fill_between(x+3,0,mlab.normpdf(x, mu, sigma), color='blue',alpha=0.5,label="PEAK3", interpolate=True)
axis[0].fill_between(x+7,0,mlab.normpdf(x, mu, sigma), color='red',alpha=0.5,label="PEAK4", interpolate=True)
axis[0].plot(x2,2.5*mlab.normpdf(x2, mu2, sigma2),color='black',linestyle="",label="Exp", marker="o", markersize=4)
axis[1].fill_between(x+6,0,mlab.normpdf(x, mu, sigma), color='green',alpha=0.5,label="PEAK1", interpolate=True)
axis[1].fill_between(x+4,0,mlab.normpdf(x, mu, sigma), color='purple',alpha=0.5,label="PEAK2", interpolate=True)
axis[1].fill_between(x+3,0,mlab.normpdf(x, mu, sigma), color='blue',alpha=0.5,label="PEAK3", interpolate=True)
axis[1].fill_between(x+7,0,mlab.normpdf(x, mu, sigma), color='red',alpha=0.5,label="PEAK4", interpolate=True)
axis[1].fill_between(x+6.5,0,mlab.normpdf(x, mu, sigma), color='yellow',alpha=0.5,label="PEAK5", interpolate=True)
axis[1].plot(x2,2.5*mlab.normpdf(x2, mu2, sigma2),color='black',linestyle="",label="Exp", marker="o", markersize=4)
axis[2].fill_between(x+6,0,mlab.normpdf(x, mu, sigma), color='green',alpha=0.5,label="PEAK1", interpolate=True)
axis[2].fill_between(x+4,0,mlab.normpdf(x, mu, sigma), color='orange',alpha=0.5,label="PEAK2", interpolate=True)
axis[2].fill_between(x+3,0,mlab.normpdf(x, mu, sigma), color='#73d216',alpha=0.5,label="PEAK3", interpolate=True)
axis[2].fill_between(x+7,0,mlab.normpdf(x, mu, sigma), color='red',alpha=0.5,label="PEAK4", interpolate=True)
axis[2].plot(x2,2.5*mlab.normpdf(x2, mu2, sigma2),color='black',linestyle="",label="Exp", marker="o", markersize=4)
axis[3].fill_between(x+6,0,mlab.normpdf(x, mu, sigma), color='green',alpha=0.5,label="PEAK1", interpolate=True)
axis[3].fill_between(x+4,0,mlab.normpdf(x, mu, sigma), color='purple',alpha=0.5,label="PEAK2", interpolate=True)
axis[3].fill_between(x+3,0,mlab.normpdf(x, mu, sigma), color='blue',alpha=0.5,label="PEAK3", interpolate=True)
axis[3].fill_between(x+7,0,mlab.normpdf(x, mu, sigma), color='red',alpha=0.5,label="PEAK4", interpolate=True)
axis[3].fill_between(x+6.5,0,mlab.normpdf(x, mu, sigma), color='#73d216',alpha=0.5,label="PEAK5", interpolate=True)
axis[3].fill_between(x+5.5,0,mlab.normpdf(x, mu, sigma), color='violet',alpha=0.5,label="PEAK6", interpolate=True)
axis[3].plot(x2,2.5*mlab.normpdf(x2, mu2, sigma2),color='black',linestyle="",label="Exp", marker="o", markersize=4)
for i in range(nrows):
h, l = axis[i].get_legend_handles_labels()
for hi, li in zip(h,l):
if not is_inlist(hi, lines):
lines.append(hi)
labels.append(li)
# only 3 Legend entrys Label1 , Label2 and Label3 are visible .. Differences in cloors and markers are ignored
plt.legend(handles=lines, labels=labels,bbox_to_anchor=(0., nrows-1+.02, 1., .102), loc=3,ncol=3, prop=legend_properties,mode="expand", borderaxespad=0.,frameon=False,framealpha=0.0)
plt.show()
由于我同时具有matplotlib.collections.PolyCollection)和matplotlib.lines.Line2D对象,因此需要比较我的真实数据.
Here my real data is reflected better as i have both matplotlib.collections.PolyCollection) and matplotlib.lines.Line2D objects wich need to be compared.
推荐答案
Edit2看起来很有希望.然后,您可以检查标签是否已在标签列表中,如果没有,请附加标签.当然,我无法测试以下内容,但至少应显示出该概念.
The Edit2 looks promising. You can then check if the label is already in the labels list and if not, append it. Of course I cannot test the following, but it should at least show the concept.
lines=[]
labels=[]
for idata, datafile in enumerate(datafiles):
MYData = The_predefined_plotting_class.from_file(datafile)
axis[idata] = The_predefined_plotting_class.get_plot( *kwargs)
h, l = axis[idata].get_legend_handles_labels()
for handle, label in zip(h, l):
if label not in labels:
lines.append(handle)
labels.append(label)
plt.legend(handles=lines, labels=labels, loc="upper left", bbox_to_anchor=[0, 1],ncol=3, shadow=True, title="Legend", fancybox=True)
plt.show()
如果要避免重复使用手柄,可以使用使它们看起来相等的属性,并查看手柄列表中是否已经存在类似的艺术家.
If you want to aviod diplicate handles, you may use the properties which make them appear equal and see if a similar artist is already present in the handles list.
def is_inlist(handle, handles):
for h in handles:
if h.get_color() == handle.get_color() and \
h.get_linestyle() == handle.get_linestyle() and \
h.get_marker() == handle.get_marker():
return True
return False
lines=[]
labels=[]
for i in range(nrows):
h, l = axis[i].get_legend_handles_labels()
for hi, li in zip(h,l):
if not is_inlist(hi, lines):
lines.append(hi)
labels.append(li)
plt.legend(handles=lines, labels=labels)
这篇关于具有不同内容的子图的全球图例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!