2014-09-12 20 views
36

Was ist die beste Praxis eine Zeile und eine Spaltenüberschrift auf ein Raster von Nebenhandlungen in einer Schleife in matplotlib erzeugt hinzufügen? Ich kann von ein paar denken, aber nicht besonders ordentlich:Zeilen- und Spaltenüberschriften in matplotlib der Nebenhandlungen

  1. Für Spalten, mit einem Zähler auf der Schleife Sie set_title() für die erste Zeile nur verwenden können. Für Zeilen funktioniert das nicht. Sie würden text außerhalb der Grundstücke ziehen haben.
  2. Sie eine zusätzliche Zeile von Nebenhandlungen oben und eine zusätzliche Spalte von Nebenhandlungen auf der linken Seite hinzufügen und Text in der Mitte dieses subplot ziehen.

Können Sie eine bessere Alternative?

enter image description here

Antwort

35

Es gibt mehrere Möglichkeiten, dies zu tun. Der einfachste Weg ist die y-Etiketten und Titel der Handlung ausnutzt, und dann fig.tight_layout() Raum für die Etiketten zu machen verwenden. Alternativ können Sie mit annotate Ergänzungstext an der richtigen Stelle platzieren und dann machen Zimmer-manuell.


Wenn Sie auf Ihren Achsen y-Etikett nicht haben, ist es einfach, den Titel und die y-Label der ersten Zeile und Spalte der Achsen zu nutzen.

import matplotlib.pyplot as plt 

cols = ['Column {}'.format(col) for col in range(1, 4)] 
rows = ['Row {}'.format(row) for row in ['A', 'B', 'C', 'D']] 

fig, axes = plt.subplots(nrows=4, ncols=3, figsize=(12, 8)) 

for ax, col in zip(axes[0], cols): 
    ax.set_title(col) 

for ax, row in zip(axes[:,0], rows): 
    ax.set_ylabel(row, rotation=0, size='large') 

fig.tight_layout() 
plt.show() 

enter image description here


Wenn Sie y-Etiketten zu tun haben, oder wenn Sie ein bisschen mehr Flexibilität wünschen, können Sie annotate verwenden, um die Etiketten zu platzieren. Dies ist komplizierter, aber Sie können neben den Zeilen- und Spaltenbeschriftungen auch einzelne Plottitel, Ylabels usw. verwenden.

import matplotlib.pyplot as plt 
from matplotlib.transforms import offset_copy 


cols = ['Column {}'.format(col) for col in range(1, 4)] 
rows = ['Row {}'.format(row) for row in ['A', 'B', 'C', 'D']] 

fig, axes = plt.subplots(nrows=4, ncols=3, figsize=(12, 8)) 
plt.setp(axes.flat, xlabel='X-label', ylabel='Y-label') 

pad = 5 # in points 

for ax, col in zip(axes[0], cols): 
    ax.annotate(col, xy=(0.5, 1), xytext=(0, pad), 
       xycoords='axes fraction', textcoords='offset points', 
       size='large', ha='center', va='baseline') 

for ax, row in zip(axes[:,0], rows): 
    ax.annotate(row, xy=(0, 0.5), xytext=(-ax.yaxis.labelpad - pad, 0), 
       xycoords=ax.yaxis.label, textcoords='offset points', 
       size='large', ha='right', va='center') 

fig.tight_layout() 
# tight_layout doesn't take these labels into account. We'll need 
# to make some room. These numbers are are manually tweaked. 
# You could automatically calculate them, but it's a pain. 
fig.subplots_adjust(left=0.15, top=0.95) 

plt.show() 

enter image description here

+1

Die Methoden 'is_first_col()', 'is_last_col()', 'is_first_row()' und 'is_last_row()' kann auch in diesem Zusammenhang nützlich sein. – gerrit

1

Die obige Antwort funktioniert. dass nicht nur in der zweiten Version der Antwort, Sie haben:

for ax, row in zip(axes[:,0], rows): 
    ax.annotate(col, xy=(0, 0.5), xytext=(-ax.yaxis.labelpad-pad,0), 
       xycoords=ax.yaxis.label, textcoords='offset points', 
       size='large', ha='right', va='center') 

statt:

for ax, row in zip(axes[:,0], rows): 
    ax.annotate(row,xy=(0, 0.5), xytext=(-ax.yaxis.labelpad-pad,0),      
       xycoords=ax.yaxis.label, textcoords='offset points', 
       size='large', ha='right', va='center') 
Verwandte Themen