2012-08-02 7 views
8

Ich bin nicht in der Lage, einen einfachen, vertikalen Pfeil im folgenden lügt-log Plot zu zeichnen:Matplotlib: Zeichnen Sie einen vertikalen Pfeil in einem lügt-log Plot

#!/usr/bin/python2 

import matplotlib.pyplot as plt 
import matplotlib as mpl 

plt.yscale('log') 
plt.xscale('log') 
plt.ylim((1e-20,1e-10)) 
plt.xlim((1e-12,1)) 

plt.arrow(0.00006666, 1e-20, 0, 1e-8 - 1e-20, length_includes_head=True) 

plt.savefig('test.pdf') 

Es zeigt einfach nicht. Aus der Dokumentation sieht es so aus, als ob alle Argumente wie Breite, Höhe usw. sich auf die Skalierung der Achse beziehen. Dies ist sehr kontraintuitiv. Ich habe versucht, twin() des Axisartist-Pakets zu verwenden, um eine Achse oben auf meiner mit Begrenzungen (0,1), (0,1) zu definieren, um mehr Kontrolle über die Parameter des Pfeils zu haben, aber ich konnte nicht herausfinden, wie man eine völlig unabhängige Achse über der primären hat .

Irgendwelche Ideen?

+1

scheint ein Problem mit Matplotlib. Versuchen Sie 'plt.arrow '(6e-4, 1e-4, 0.1, 0.2, length_includes_head = True)' und verschieben Sie die Ansicht um einen höheren Wert von y. Sie werden die Pfeillinie ab etwa 10-4 sehen. Wenn Sie jedoch niedrigere Werte verwenden (dh 1e-5 für x und y), verschwindet die Linie und Sie können nur den kleinen Pfeilkopf an der gleichen Stelle wie zuvor sehen. (Natürlich sollten Sie plt.show() dazu verwenden) – joaquin

+0

Gibt es also einen Workaround? – janoliver

+0

Wenn ich etwas weiß, hätte ich eine Antwort geschrieben ;-). Aber jetzt weißt du wenigstens, dass der Pfeil da ist ... – joaquin

Antwort

4

Nebenhandlungen nähern

Nachdem die Nebenhandlungen Erstellen Sie die folgende

  • die Positionen ausrichten
  • Verwenden set_axis_off() die Achse auszuschalten (Ticks, Etiketten, etc.)
  • dem DRAW Pfeil!

So ein paar Zeilen bekommt, was Sie wollen!

z.

#!/usr/bin/python2 

import matplotlib.pyplot as plt 

hax = plt.subplot(1,2,1) 
plt.yscale('log') 
plt.xscale('log') 
plt.ylim((1e-20,1e-10)) 
plt.xlim((1e-12,1)) 

hax2 = plt.subplot(1,2,2) 
plt.arrow(0.1, 1, 0, 1, length_includes_head=True) 

hax.set_position([0.1, 0.1, 0.8, 0.8]) 
hax2.set_position([0.1, 0.1, 0.8, 0.8]) 

hax2.set_axis_off() 

plt.savefig('test.pdf') 

Rescale Daten

Alternativ kann ein möglicherweise einfacher Ansatz, obwohl die Achsenbeschriftungen schwierig sein kann, ist es, die Daten neu zu skalieren.

heißt

import numpy 

# Other import commands and data input 

plt.plot(numpy.log10(x), numpy.log10(y))) 

nicht eine große Lösung, aber ein gutes Ergebnis, wenn Sie die Zecke Etiketten verarbeiten kann!

+0

Hallo, ich würde dafür eine separate x UND Achse benötigen, da beide in der Host Achse logarithmisch skaliert sind. Die "Twin" -Funktion von Axisartists verwendet immer eine Transformationsfunktion zwischen dem Wirt und der Parasitenachse. Ich möchte nicht, dass sie irgendwie miteinander verbunden sind. Da die Dokumentation über diese Dinge so schlecht ist, konnte ich keinen (möglicherweise nicht-schmutzigen) Weg finden, dies zu erreichen. Wenn es nicht leicht machbar ist, werde ich wahrscheinlich nur die Pfeile mit Inkscape oder so einfügen. – janoliver

+0

Die Überlagerung. Ich kann mir nicht vorstellen, zwei völlig unabhängige Plots übereinander zu haben, jede mit ihrer eigenen x- und y-Achse und so weiter. – janoliver

+0

Warum also nicht einfach eine lineare Darstellung von 'log (x)' und 'log (y)'? Es macht das Zeichnen des Pfeils trivial. – jmetz

5

Ich suchte nach einer Antwort auf diese Frage und fand eine nützliche Antwort! Sie können jedes "Mathtext" -Zeichen (Matplotlibs LaTeX-Version) als Markierung angeben. Versuchen Sie: plt.plot (x, y, 'ko', marker = r '$ \ downarrow $', markergröße = 20)

Dies wird einen nach unten zeigenden, schwarzen Pfeil an der Position (x, y), dass sieht auf jedem Diagramm gut aus (sogar log-log). Siehe: matplotlib.org/users/mathtext.html#mathtext-tutorial für mehr Symbole, die Sie verwenden können.

1

Ich weiß, dass dieser Thread schon lange tot ist, aber ich denke, meine Lösung könnte hilfreich für jeden sein, der versucht herauszufinden, wie man Pfeile auf Log-Scale-Plots effizient zeichnet.

Alternativ zu dem, was andere bereits geschrieben haben, könnten Sie eine transformation object verwenden, um die Pfeilkoordinaten nicht im Maßstab der Originalachsen, sondern im (linearen) Maßstab der "Achsenkoordinaten" einzugeben. Was ich unter Achsenkoordinaten verstehe, sind diejenigen, die auf [0,1] (horizontaler Bereich) um [0,1] (vertikaler Bereich) normalisiert sind, wobei der Punkt (0,0) die untere linke Ecke und der Punkt wäre (1,1) wäre die obere rechts, und so weiter.Dann schließen Sie könnten einfach einen Pfeil durch:

plt.arrow(0.1, 0.1, 0.9, 0.9, transform=plot1.transAxes, length_includes_head=True) 

Dies gibt einen Pfeil, der diagonal über 4/5 des Grundstücks der horizontalen und vertikalen Bereich erstreckt sich von unten links nach oben rechts (wo plot1 das ist Unterplot-Name).

Wenn Sie wollen, dass diese im Allgemeinen zu tun, wo genau (x0,y0) und (x1,y1) im Log-Raumkoordinaten für den Pfeil angegeben wird, dann ist dies nicht allzu schwierig, wenn Sie zwei Funktionen fx(x) und fy(y), die von der ursprünglichen Koordinaten-Transformation schreiben zu diesen "Achsen" -Koordinaten. Ich habe ein Beispiel gegeben, wie der ursprüngliche Code, der vom OP gepostet wurde, modifiziert werden könnte, um dies unten zu implementieren (Entschuldigung dafür, dass ich die Bilder, die der Code produziert, nicht mit einbeziehe, habe ich noch nicht die erforderliche Reputation).

#!/usr/bin/python3 

import numpy as np 
import matplotlib.pyplot as plt 
import matplotlib as mpl 

# functions fx and fy take log-scale coordinates to 'axes' coordinates 
ax = 1E-12 # [ax,bx] is range of horizontal axis 
bx = 1E0 
def fx(x): 
    return (np.log(x) - np.log(ax))/(np.log(bx) - np.log(ax)) 

ay = 1E-20 # [ay,by] is range of vertical axis 
by = 1E-10 
def fy(y): 
    return (np.log(y) - np.log(ay))/(np.log(by) - np.log(ay)) 

plot1 = plt.subplot(111) 
plt.xscale('log') 
plt.yscale('log') 
plt.xlim(ax, bx) 
plt.ylim(ay, by) 

# transformed coordinates for arrow from (1E-10,1E-18) to (1E-4,1E-16) 
x0 = fx(1E-10) 
y0 = fy(1E-18) 
x1 = fx(1E-4) - fx(1E-10) 
y1 = fy(1E-16) - fy(1E-18) 

plt.arrow(
      x0, y0, x1, y1, # input transformed arrow coordinates 
      transform = plot1.transAxes, # tell matplotlib to use axes coordinates 
      facecolor = 'black', 
      length_includes_head=True 
     ) 

plt.grid(True) 
plt.savefig('test.pdf') 
Verwandte Themen