In der Tat kommt die Bounding Box des Textes in Einheiten im Gegensatz zu denen, die zum Beispiel in Scatterplot verwendet werden. Text ist eine andere Art von Objekt, das irgendwie neu gezeichnet wird, wenn Sie die Größe des Fensters ändern oder das Verhältnis ändern. Durch ein stabilisiertes Fenster aufweisen, können Sie die Koordinaten des Begrenzungsrahmens in Plot Einheiten stellen und Ihre farbigen Text auf diese Weise bauen:
a = "all unicorns poop rainbows ! ! !".split()
c = ['red', 'orange', 'brown', 'green', 'blue', 'purple', 'black']
f = plt.figure(figsize=(4,3), dpi=120)
ax = f.add_subplot(111)
r = f.canvas.get_renderer()
space = 0.1
w = 0.5
counter = 0
for i in a:
t = ax.text(w, 1.2, a[counter],color=c[counter],fontsize=12,ha='left')
transf = ax.transData.inverted()
bb = t.get_window_extent(renderer=f.canvas.renderer)
bb = bb.transformed(transf)
w = w + bb.xmax-bb.xmin + space
counter = counter + 1
plt.ylim(0.5,2.5)
plt.xlim(0.6,1.6)
plt.show()
, was zur Folge hat:
Dies ist jedoch , ist immer noch nicht ideal, da Sie die Größe Ihrer Diagrammachse steuern müssen, um die richtigen Abstände zwischen Wörtern zu erhalten. Dies ist etwas willkürlich, aber wenn Sie es schaffen, Ihr Programm mit einer solchen Kontrolle zu machen, ist es möglich, Plot-Einheiten zu verwenden, um Ihren beabsichtigten Zweck zu erreichen.
ORIGINAL POST:
plt.
ist nur der Aufruf der Bibliothek. In Wirklichkeit erstellen Sie eine Instanz von plt.figure
im globalen Gültigkeitsbereich (so kann es lokal in der Funktion gesehen werden). Aus diesem Grund überschreiben Sie die figure
, weil Sie den gleichen Namen für die Variable verwenden (es ist also nur eine einzige Instanz am Ende). Um dies zu lösen, versuche die Namen deiner Figureninstanzen zu kontrollieren. Zum Beispiel:
import matplotlib.pyplot as plt
#%matplotlib inline
from matplotlib import transforms
fig = plt.figure(figsize=(4,3), dpi=300)
#plt.show(fig)
def rainbow_text(x,y,ls,lc,**kw):
t = plt.gca().transData
figlocal = plt.gcf()
#horizontal version
for s,c in zip(ls,lc):
text = plt.text(x,y," "+s+" ",color=c, transform=t, **kw)
text.draw(figlocal.canvas.get_renderer())
ex = text.get_window_extent()
t = transforms.offset_copy(text._transform, x=ex.width, units='dots')
plt.show(figlocal) #plt.show((figlocal,fig))
#plt.figure()
rainbow_text(0.5,0.5,"all unicorns poop rainbows ! ! !".split(),
['red', 'orange', 'brown', 'green', 'blue', 'purple', 'black'],
size=40,)
Ich habe mehrere Anweisungen kommentiert aber bemerke ich einen anderen Namen geben für die figure
lokal für die Funktion (figlocal
). Beachte auch, dass ich in meinen Showbeispielen direkt kontrolliere, welche figure
angezeigt werden soll.
Was Ihre anderen Fragen beachten Sie, andere Geräte verwenden können, wie in der Funktion Dokumentation zu sehen:
Return a new transform with an added offset.
args:
trans is any transform
kwargs:
fig is the current figure; it can be None if units are 'dots'
x, y give the offset
units is 'inches', 'points' or 'dots'
EDIT: Anscheinend ist es eine Art von Problem mit den Ausmaßen des Begrenzungsrahmens für Text, der tut geben Sie nicht die richtige Breite des Wortes und somit ist der Abstand zwischen Wörtern nicht stabil. Ich rate dazu, die Latex-Funktionalität von Matplotlib zu verwenden, um die Farben in dieselbe Zeichenfolge zu schreiben (also nur einen Aufruf von plt.text). Sie können es so tun:
import matplotlib
import matplotlib.pyplot as plt
matplotlib.use('pgf')
from matplotlib import rc
rc('text',usetex=True)
rc('text.latex', preamble=r'\usepackage{color}')
a = "all unicorns poop rainbows ! ! !".split()
c = ['red', 'orange', 'brown', 'green', 'blue', 'purple', 'black']
st = ''
for i in range(len(a)):
st = st + r'\textcolor{'+c[i]+'}{'+a[i]+'}'
plt.text(0.5,0.5,st)
plt.show()
Dies ist jedoch keine ideale Lösung. Der Grund ist, dass Sie Latex installiert haben müssen, einschließlich der notwendigen Pakete (beachten Sie, dass ich das Farbpaket verwende). Werfen Sie einen Blick auf Yann Antwort in dieser Frage:
Danke, @armatita aber wie steuere ich (wirklich, regularisieren) die Breite für eine gegebene Einheit? Ich frage, weil diese Beispiele inkonsistente Abstände zwischen Wörtern erzeugen, was ich letztendlich zu beheben versuche (bezüglich des zweiten Teils meiner Frage). –
@Dance Party2 Wenn diese Transformation nicht den richtigen Weg macht, vergiss einfach die Transformation. Definieren Sie Ihre Schriftart, Ausrichtung und plotten Sie jedes Wort mit Koordinaten. Beachten Sie, dass Sie bereits die Bounding-Box des Textes erhalten (text.get_window_extent()), so dass Sie z. B. sagen können, dass ein Leerzeichen 0,2 bedeutet, dass Word2 in Word1_Width + 0,2 positioniert sein soll (und so weiter für Word3) wird sich selbst eine Art Transformation aufbauen. Die Sache ist, ich bin mir nicht sicher, was diese Transformation, die Sie verwenden, tatsächlich tut. Auch: http://stackoverflow.com/questions/5320205/matplotlib-text-dimensions – armatita
Ja! Ich danke dir sehr! Das wird mir Stunden Zeit sparen. Wenn du das als Antwort posten willst, nehme ich es gerne an. –