2016-04-15 5 views
0

ich eine Datendatei, die wie folgt aussieht:Mehrere Datenblocks in einer einzigen Datei und eine einzelne Parzelle + Marker für jeden Block

"curve 0" 
0 0.7800 
10 0.333 
12 0.5136 
24 0.2096 
26 -0.066 
40 -0.674 
42 -1.123 


"curve 1" 
0 0.876 
2 0.73 
4 0.693 
6 0.672 
10 0.70 
12 0.88 
16 0.95 
148 -0.75 


"curve 2" 
8 2.2305 
10 2.144 
12 2.13 
76 1.26 
78 0.39 
98 -0.97 

Ich mag jeden Block von Daten von den anderen unabhängig plotten mit Gnuplot. Hier ist der Code, den ich für diesen Zweck verwende:

plot 'file' i 0 u 1:2 w lines title columnheader(1),\ 
'file' i 1 u 1:2 w lines title columnheader(1),\ 
'file' i 2 u 1:2 w lines title columnheader(1),\ 
'file' i 3 u 1:2 w lines title columnheader(1) 

Es funktioniert gut.

Nun möchte ich in jedem Datenblock den Punkt (x, y) bestimmen, der den maximalen y-Wert hat, und ihn mit einem Marker versehen, der die gleiche Farbe wie die diesem Datenblock entsprechende Kurve hat. Ich habe versucht,

max_y = GPVAL_DATA_Y_MAX 
replot 'file' u ($2 == max_y ? $2 : 1/0):1 

nach dem vorherigen Code zu verwenden, aber es scheint, dass dies das Maximum über die gesamte zweite Säule einschließlich aller Blöcke findet. Die zweite Sache, die ich tun möchte, ist: für jeden Datenblock und mit einem Marker, der eine andere Form hat, aber die gleiche Farbe (die der Kurve) als die Markierung für die Maxima, plotten Sie die erste Zeile davon Block.

Sind diese beiden Aufgaben mit gnuplot möglich und mit der Art, wie ich die Kurven zeichne (columnheader)?

Antwort

2

Dies kann getan werden. Es wird den Befehl stats ausgiebig und eine temporäre Datei verwenden. In gnuplot 5 kann die temporäre Datei unter Verwendung eines benannten Datenblocks im Speicher erstellt werden (siehe help datablocks).

Zusätzlich als Plotbefehl weitgehend wiederholend ist, können Sie die Handlung für Syntax

plot for[in=0:2] 'file' i in u 1:2 w lines t columnheader(1) 

können

die den Plotbefehl mit den Werten 0 bis 2 für die Variable in (Ihr bereitgestellt Befehl vier wiederholt verwendet Datenblöcke, aber Ihre bereitgestellte Datendatei hat nur 3).

wird Das folgende Skript erreichen, was Sie wollen:

stats 'file' u 1:2 nooutput 
blocks = STATS_blocks 

set print 'tempfile' 

first_y = "" 
first_x = "" 
do for[i=0:blocks-1] { 
    stats 'file' index i u (first_x=($0==1)?sprintf("%s %f",first_x,$1):first_x,first_y=($0==1)?sprintf("%s %f",first_y,$2):first_y,$1):2 nooutput 
    print sprintf("%f %f",STATS_pos_max_y,STATS_max_y) 
} 

print "" 
print "" 
do for[i=1:blocks] { 
    print sprintf("%s %s",word(first_x,i),word(first_y,i)) 
} 
set print 

plot for[i=0:blocks-1] 'file' i i u 1:2 w lines title columnheader(1),\ 
    for[i=0:1] 'tempfile' i i u 1:2:($0+1) w points pt (i==0?7:9) lc variable not 

Dies erzeugt (mit Ihrem versehen Datenfile)

enter image description here

Im Fall der Kurve 0 und 2, die ersten und die maximalen Punkte sind gleich, so dass die Symbole verdeckt sind.

Wenn wir dies wiederholen, aber die Spezifikation ändern, um die ersten Punktmarkierungen um 0,1 zu erhöhen, können wir sehen, dass sie dort auftauchen, wo sie hingehören.

enter image description here


Dieser Abschnitt lang sein wird, aber ich werde den Code und erklären im Detail, so nahe Zeile für Zeile wie möglich abbauen, weil es ein paar subtile Dinge sind in Hier.

Die ersten beiden Zeilen

stats 'file' u 1:2 nooutput 
blocks = STATS_blocks 

Lauf gebiete die Statistiken über die Datei.Aufgrund der benannten Spaltenüberschriften schlägt die stats-Funktion fehl, wenn wir keine using-Spezifikation angeben, daher geben wir ihr die u 1:2-Spezifikation. Die Option nooutput teilt dem Befehl stats mit, die Ergebnisse zu erfassen, sie jedoch nicht auszugeben. Hier kümmern wir uns nur um die Anzahl der Blöcke. Wir speichern dies in der Variablen Blöcke (da spätere Statistikbefehle die Variable überschreiben). Wir hätten ein benanntes Präfix angeben können, aber das hätte alle Variablen gespeichert, und dafür gibt es keinen Grund. Anstelle dieser beiden Befehle hätten wir im Fall von genau 3 Blöcken den Wert 3 für alle Vorkommen von Blöcken unten einfach ersetzen können, aber auf diese Weise ist die Anzahl der Blöcke nicht fest codiert.

Als nächstes verwenden wir set print 'tempfile', um Druckbefehle in eine temporäre Datei umzuleiten. Wir werden eine neue Datei erstellen, die die maximalen Punkte und die ersten Punkte enthält.

Der nächste Codeabschnitt

first_y = "" 
first_x = "" 
do for[i=0:blocks-1] { 
    stats 'file' index i u (first_x=($0==1)?sprintf("%s %f",first_x,$1):first_x,first_y=($0==1)?sprintf("%s %f",first_y,$2):first_y,$1):2 nooutput 
    print sprintf("%f %f",STATS_pos_max_y,STATS_max_y) 
} 

ist die schwierigste und wo die meisten der Magie passiert. Wir werden unsere temporäre Datei erstellen, um zwei Datenblöcke zu haben. Der erste ist der Maximalwert und der zweite ist der erste Wert. Wir berechnen die ersten Punkte im Speicher und fügen sie hinzu, nachdem wir diesen ersten Datenblock erstellt haben. Die x-Koordinaten und y-Koordinaten werden in einer durch Leerzeichen getrennten String-Variablen gespeichert.

Wir durchlaufen alle Datenblöcke und berechnen einen Statistikbefehl dafür. Der Ausdruck

(first_x=($0==1)?sprintf("%s %f",first_x,$1):first_x,first_y=($0==1)?sprintf("%s %f",first_y,$2):first_y,$1) 

ordnet die zwei Stringvariablen für jeden Punkt lesen. Um dies zu tun, ist es zunächst überprüft, ob der Punkt, der ersten in der Reihe ist (der Wert von $ 0 wird 1 sein, da der Wert 0 entspricht die Kopfzeile). Wenn dies der Fall ist, wird die Zeichenfolgenvariable neu erstellt, indem der Wert der ersten Spalte (und ähnlich für die y-Koordinaten) hinzugefügt wird. Ansonsten wird der Variablen einfach dasselbe zugewiesen. Schließlich gibt es den Wert in der ersten Spalte zurück. Wenn Ausdrücke in Klammern gesetzt und ein Komma wie folgt getrennt wird, wird jeder Ausdruck der Reihe nach ausgewertet, und der endgültige Wert wird zurückgegeben.

So sind die Statistiken Befehl verhält sich wie es

war
stats 'file' index i u 1:2 nooutput 

aber dieser kleine Trick erlaubt es uns, die erste Zeile Werte zu lesen und speichern, wenn sie hereinkommen. Schließlich wird der Punkt mit dem maximalen y-Wert wird ausgedruckt . Dies wird in die temporäre Datei gehen.

Jetzt müssen wir die ersten Punkte der temporären Datei als neuen Datenblock hinzufügen. Also zuerst drucken wir zwei leere Zeilen und dann wieder wir die Anzahl der Blöcke durchlaufen Lauf

print sprintf("%s %s",word(first_x,i),word(first_y,i)) 

für jeden Block (wobei i die Nummer des Blocks). Die Wortfunktion behandelt eine String-Variable als eine durch Leerzeichen getrennte Liste von Wörtern und zieht das angeforderte Wort ab. An dieser Stelle sehen unsere String-Variablen wie

0.000000 0.000000 8.000000 # first_x 
0.780000 0.876000 2.230500 # first_y 

Schließlich haben wir set print ausgeben, die den Druckbefehl an die Konsole drucken wieder her. Wir haben nun eine temporäre Datei erstellt, die wie

0.000000 0.780000 
16.000000 0.950000 
8.000000 2.230500 


0.000000 0.780000 
0.000000 0.876000 
8.000000 2.230500 

sieht, wo der erste Datenblock die Punkte mit dem maximalen y-Wert sind und der zweite Datenblock die ersten Punkte sind.

Schließlich tragen wir mit

plot for[i=0:blocks-1] 'file' i i u 1:2 w lines title columnheader(1),\ 
    for[i=0:1] 'tempfile' i i u 1:2:($0+1) w points pt (i==0?7:9) lc variable not 

Der erste Teil dieser ist identisch vor, nur mit den variablen Blöcken statt Hartcodierung der Anzahl von Blöcken verwendet.

Als nächstes zeichnen wir die temporäre Datei zweimal mit Index 0 und Index 1. Die Linienfarbe ist variabel basierend auf der Zeilennummer (in diesem Fall 0 bis 2). Wir fügen einen hinzu, um die normalerweise 0-basierte Zeilennummer zu 1 bis 3 zu machen. Dies entspricht den Datenblöcken von vorher. Wir zeichnen mit Punkten und wählen den Punkttyp basierend auf dem Datenblock, den wir zeichnen. Es ist entweder ein gefüllter Kreis (für das Maximum) oder ein ausgefülltes Dreieck (für die ersten Punkte) in diesem Fall.

+0

Hallo Matthew! Vielen Dank für die Erklärung, die Sie gegeben haben. Ich kenne nur grundlegende Befehle von gnuplot. Es war also sehr hilfreich. Ich denke, Ihre Antwort ist eine gute Einführung in den anspruchsvollen Gnuplot-Code. Danke noch einmal. – dada

Verwandte Themen