2017-07-06 1 views
1

J'ai lu les solutions précédentes, mais je ne pouvais pas faire fonctionner l'une d'entre elles. Je veux avoir une légende globale pour les sous-placettes individuelles. Les objets de hache pour cette sous-parcelle sont générées par une fonction prédéfinie de « get_plot » hors d'une classe prédéfinie « The_predefined_plotting_class » à peu près comme suit:Légende globale pour les intrigues secondaires avec un contenu différent

My code

la fonction retourne un objet de hache et chacun des objets de hache comporte plusieurs "tracés"/à partir de plusieurs colonnes des "fichiers de données" d'origine.

Dans l'une des solutions i S'Y TROUVE je lis que je pourrais utiliser:

enter image description here

pour faire une légende mondiale. Malheureusement, je n'ai aucune idée de comment ajouter les objets ax (ou les données) à des poignées pour que cela fonctionne. Chaque graphique contient des noms de colonnes identiques et d'autres qui diffèrent. Si une entrée/nom existe dans plusieurs sous-placettes, il ne devrait être imprimé qu'une seule fois.

Solution1

Solution2

Solution3

EDIT

Je suis vraiment désolé que je devais utiliser des images, mais tout ce que je faisais la webside ne me laisse pas poster mon code même s'il a été affiché correctement dans la fenêtre d'aperçu (les captures d'écran proviennent de cette fenêtre)

EDIT2

Si je le fais comme ceci:

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() 

Ensuite, il affiche toutes les données. Certaines données ont le même gestionnaire de lignes et d'étiquettes. Je suis maintenant à gauche avec le problème pour parcourir les deux listes et supprimer une seule entrée si dans les deux listes le tuple(LINES [j]; LABELS [j]) = (LIGNES [i]; ÉTIQUETTES [i]) existe deux fois (et seulement alors). De préférence, la première entrée:

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

ajouter un "minimum" exemple de travail qui doit contenir toutes les situations qui se produisent dans mes données réelles.

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

c'est la partie forme le script en question où les parcelles réels sont générés. "columns" contient uniquement les noms des données réelles à tracer.

# 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

J'ai essayé de trouver une solution basée sur l'idée que je présentais ici:

Iteration though lists

Malheureusement ce qui fonctionne pour deux listes contenant des chaînes ne fonctionne pas pour la artiste poignées il semble.

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() 

Je pense que le problème est que seule la chaîne pour l'adresse de mémoire est comparée dans

if hl not in LI: 

pas le contenu réel de « h »?

solution basée sur l'explication de ImportanceOfBeingErnest a donné dans un poste lié 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() 

Voici reflète mieux mes données réelles que j'ai à la fois matplotlib.collections.PolyCollection) et matplotlib.lines.Line2D objets qui doivent être comparés.

+0

Aucune des solutions dans les questions liées a travaillé pour vous? Je suggère un simple 'ax.legend (bbox_to_anchor = (1.05, 0), loc = 'centre inférieur', borderaxespad = 0.)' –

+0

Vous devez taper le code manuellement, d'une manière ou d'une autre, vous collez des captures d'écran de le code. – ngoldbaum

+0

si je fais ce que vous suggérez je reçois: AttributeError: l'objet 'numpy.ndarray' n'a pas d'attribut 'légende'! J'ai ajouté une question ci-dessus. – NorrinRadd

Répondre

1

L'Edit2 semble prometteur. Vous pouvez ensuite vérifier si l'étiquette est déjà dans la liste des étiquettes et, si ce n'est pas le cas, l'ajouter. Bien sûr, je ne peux pas tester ce qui suit, mais il devrait au moins montrer le 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() 

Si vous voulez aviod poignées de diplicate, vous pouvez utiliser les propriétés qui leur paraissent égales et voir Émettre si un artiste similaire est déjà présent dans la liste des poignées.

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) 

enter image description here

+0

@NorrinRadd la prochaine fois s'il vous plaît fournir un [mcve]. Sinon, il est vraiment difficile de fournir de l'aide. – ImportanceOfBeingErnest

+0

Au début .... si une poignée est "connectée" à deux étiquettes la solution ci-dessus la supprime de toute façon .... Cela signifie si une sous-parcelle a et élément a qui est rouge et un autre cublot a un élément qui est coloré vert seul le premier apparaît dans la légende. Mais cela ne devrait pas être le cas. Avez-vous une idée? – NorrinRadd

+0

Comment une poignée peut-elle être connectée à deux étiquettes? En tout cas, comme je l'ai déjà dit, un [mcve] est nécessaire pour pouvoir vous fournir une bonne solution. Rappelez-vous que vous n'avez pas besoin de 'The_predefined_plotting_class' ou d'un tel exemple. Vous avez juste besoin du code de travail qui montre le problème, et, si corrigé, vous permet de résoudre votre problème. – ImportanceOfBeingErnest