2011-09-24 14 views
9

Originariamente pensavo che questo potesse essere lo stesso di gnuplot - start of X series - Stack Overflow - ma penso che questo sia leggermente più specifico.Lettura del valore del set di dati in una variabile gnuplot (inizio della serie X)

Poiché sono interessato a trovare "l'inizio della serie X", per così dire - cercherò di chiarire con un esempio; dire che hai questo script:

# generate data 
system "cat > ./inline.dat <<EOF\n\ 
10.0 1 a 2\n\ 
10.2 2 b 2\n\ 
10.4 3 a 2\n\ 
10.6 4 b 2\n\ 
10.8 5 c 7\n\ 
11.0 5 c 7\n\ 
EOF\n" 

# ranges 
set yrange [0:8] 
set xrange [0:11.5] 

plot "inline.dat" using 1:2 with impulses linewidth 2 

Se si traccia di esso, si noterà i dati parte da 10 sull'asse x:

gnuplot-startx.png

Ora, naturalmente è possibile regolare la xrange - ma a volte ti interessano le "posizioni relative" che iniziano "da 0", per così dire. Pertanto, si vorrebbe vedere i dati "spostato a sinistra" sul l'asse x, in modo che inizia a 0. Dal momento che conosciamo i dati inizia alle 10.0, potremmo sottrarre tale da prima colonna esplicitamente:

plot "inline.dat" using ($1-10.0):2 with impulses linewidth 2 

... e questo fondamentalmente fa il trucco.

Tuttavia, è possibile specificare per specificare "10.0" nel comando plot in precedenza; quindi, sapendo che è il primo elemento della prima colonna di dati che è già caricato, si spera che ci sia un modo per leggere in qualche modo questo valore in una variabile, ad esempio con lo pseudocodice seguente:

... e con qualcosa di simile, non si dovrebbe specificare questo valore "x offset", per così dire, manualmente nel comando plot.

Quindi - per riformulare - esiste un modo per leggere l'inizio della serie x (il primo valore di una data colonna in un set di dati) come variabile in gnuplot?

risposta

6

due modi:

1. tracciare la funzione prima e lasciare Gnup molto a dire il valore minimo x:

plot "inline.dat" using 1:2 with impulses linewidth 2 

xmin = GPVAL_DATA_X_MIN 
plot "inline.dat" using ($1-xmin):2 with impulses linewidth 2 

2. Usa script esterno per capire che cosa è il valore minimo x:

xmin = `sort -nk 1 inline.dat | head -n 1 | awk '{print $1}'` 
plot "inline.dat" using ($1-xmin):2 with impulses linewidth 2 
+0

Fantastico - molte grazie per la risposta concisa, @Sunhwan Jo - Cheers! – sdaau

+0

sì, MA, cosa succede se ti interessa l'elemento * primo * della serie di dati, che non deve necessariamente essere il minimo? – TMOTTM

+0

@TMOTTM quindi devi regolare lo script esterno per usare solo il primo elemento (usando awk direttamente senza la parte di ordinamento). – EverythingRightPlace

2

Hmmm ... OK, ho qualcosa:

initer(x) = (!exists("first")) ? first = x : first ; 
plot "inline.dat" using ($1-initer($1)):2 with impulses linewidth 2 

... ma questo sembra più "cattura" una variabile, di leggerlo (come la funzione initer viene utilizzato per la scansione di un flusso di numeri, rileva il primo, e tornare il suo valore) :) Spero che ci sia un modo migliore di fare questo ....

3

OK, io continuo a tornare a questo - quindi credo Avevo bisogno dei seguenti chiarimenti qui:

Dato che gnuplot, beh, plots set di dati come grafici 2D - è un dato che in qualche modo si occupa di strutture o array 2D. Questo è il motivo per cui qualcuno viene da C, Perl, Python ecc.penserebbe naturalmente che sia possibile in qualche modo indicizzare il set di dati ed essere in grado di recuperare un valore in una data riga e in una posizione di colonna; dire, qualcosa di simile al seguente pseudocodice:

my_val = "inline.dat"[1][2]  # get value in 1st row and 2nd column 

o in alternativa, pseudocodice:
my_dataset = parse_dataset("inline.dat")
my_val = get_value(my_dataset, 1, 2)

E ho passato un sacco di tempo alla ricerca di qualcosa di simile in gnuplot, e non può trovare qualcosa di simile (accesso diretto alla variabile ai valori del set di dati attraverso l'indice di riga e colonna). Sembra che il solo cosa si può fare, è plot il set di dati - e possibilmente accedere ai valori lì, tramite la funzione chiamata nella parte using.

Ciò significa, che se voglio trovare alcuni valori del set di dati da gnuplot, ho ho per scorrere il set di dati chiamando plot - anche se ho bisogno di quei valori proprio per costruire una vera e propria plot dichiarazione :) E io tipo di tavolo antipatia che, pensando che il primo plot possa in qualche modo rovinare la seconda dopo :) Tuttavia, come finding maximum value in a data set and subtracting from plot - comp.graphics.apps.gnuplot | Google Groups punti fuori, uno puòplot in un file, anche stdout o /dev/null, e ottenere un ASCII formattato - così almeno posso reindirizzare la prima chiamata in questo modo, in modo che non interferisca con l'azione terminale di tracciamento ual della seconda chiamata a plot.

Quindi, di seguito è un altro esempio di codice, in cui il primo elemento della prima colonna della "inline.dat" set di dati viene recuperato tramite:

# print and get (in _drcv) first value of first data column: 
eval print_dataset_row_column("inline.dat",0,1) 

# must "copy" the "return" value manually: 
first = _drcv 

... così poi la trama può essere compensato da first direttamente in la chiamata plot.

Nota ancora che print_dataset_row_column chiamate plot (reindirizzate tramite set table a /dev/null) - e come tale, ogni volta si chiama per recuperare un singolo valore , causerà iterazione del intera set di dati! Quindi se hai bisogno del primo elemento e dell'ultimo elemento (e probabilmente di altre cose, come some basic statistics with gnuplot), probabilmente è meglio riscrivere print_dataset_row_column in modo che recuperi tutti quelli in una volta.

È inoltre necessaria una riscrittura print_dataset_row_column se si utilizzano alcuni formati speciali nel set di dati e la riga using. Si noti che in questo esempio, la terza colonna è una stringa, che non è accettata per impostazione predefinita come colonna di dati di plot; e in quanto tale, le chiamate alle funzioni print_dataset_* non funzioneranno se devono gestirle (vedere anche gnuplot plot from string).

 

Quindi, ecco il codice di esempio - chiamiamolo test.gp:

# generate data 
system "cat > ./inline.dat <<EOF\n\ 
10.0 1 a 2\n\ 
10.2 2 b 2\n\ 
10.4 3 a 2\n\ 
10.6 4 b 2\n\ 
10.8 5 c 7\n\ 
11.0 5 c 7\n\ 
EOF\n" 

### "dry-run" functions: 
# iterate through dataset by calling 
# `plot`, redirected to file output (via `set table`) 
# 
# note: eval (not print) cannot be inside a user-defined function: 
# a(b) = eval('c=3') ; print a(4) ==> "undefined function: eval" 
# nor you can make multistatement functions with semicolon: 
# f(x) = (2*x ; x=x+2) ==> ')' expected (at ';') 
# 
# so these functions are defined as strings - and called through eval 
# 
# through a single column spec in `using`: 
# (`plot` prints table to stdout) 
# 
print_dataset_column(filename,col) = "set table '/dev/stdout' ;\ 
plot '".filename."' using ".col." ;\ 
unset table" 
# 
# through two column spec in `using`: 
# (`plot` prints table to stdout) 
# 
print_dataset_twocolumn(filename,colA,colB) = "set table '/dev/stdout' ;\ 
plot '".filename."' using ".colA.":".colB." ;\ 
unset table" 
# 
# print value of row:column in dataset, saving it as _drcv variable 
# 
# init variable 
# 
_drcv = 0 
# 
# create _drc helper function; note assign and "return" in 
# true branch of ternary clause 
# 
_drc(ri, colval, col) = (ri == _row) ? _drcv = colval : colval 
# 
# define the callable function: 
# 
print_dataset_row_column(filename,row,col) = "_row = ".row." ;\ 
set table '/dev/null' ;\ 
plot '".filename."' using (_drc($0, $".col.", ".col.")) ;\ 
unset table ;\ 
print '".filename."[r:".row.",c:".col."] = ',_drcv" 
# 
# 
### end dry run functions 


# 
# test print_dataset_* functions: 
# 

eval print_dataset_column("inline.dat",0) 
eval print_dataset_twocolumn("inline.dat",0,0) 

# string column - cannot directly: 
# set table '/dev/stdout' ;plot 'inline.dat' using 3 ;unset table 
#            ^
# line 69: warning: Skipping data file with no valid points 
# line 69: x range is invalid 
#~ eval print_dataset_column("inline.dat",3) 

eval print_dataset_column("inline.dat",1) 
eval print_dataset_twocolumn("inline.dat",1,2) 

eval print_dataset_row_column("inline.dat",4,1) 
eval print_dataset_row_column("inline.dat",4,2) 

# will fail - 3 is string column 
# line 82: warning: Skipping data file with no valid points 
# line 82: x range is invalid 
#~ eval print_dataset_row_column("inline.dat",4,3) 


# 
# do a plot offset by first element position 
# 

# print and get (in _drcv) first value of first data column: 
eval print_dataset_row_column("inline.dat",0,1) 
# must "copy" the "return" value manually: 
first = _drcv 

# ranges 
set yrange [0:8] 
set xrange [0:11.5] 

# plot finally: 
plot "inline.dat" using ($1-first):2 with impulses linewidth 2 

Quando questo script viene chiamato, il set di dati nel PO viene tracciato mosso, a partire da 0 - e il successivo viene emesso in terminal (primi stampe tavola sono l'uscita reale dal plot reindirizzato via set table a stdout):

gnuplot> load './test.gp' 

# Curve 0 of 1, 6 points 
# Curve title: "'inline.dat' using 0" 
# x y type 
0 0 i 
1 1 i 
2 2 i 
3 3 i 
4 4 i 
5 5 i 


# Curve 0 of 1, 6 points 
# Curve title: "'inline.dat' using 0:0" 
# x y type 
0 0 i 
1 1 i 
2 2 i 
3 3 i 
4 4 i 
5 5 i 


# Curve 0 of 1, 6 points 
# Curve title: "'inline.dat' using 1" 
# x y type 
0 10 i 
1 10.2 i 
2 10.4 i 
3 10.6 i 
4 10.8 i 
5 11 i 


# Curve 0 of 1, 6 points 
# Curve title: "'inline.dat' using 1:2" 
# x y type 
10 1 i 
10.2 2 i 
10.4 3 i 
10.6 4 i 
10.8 5 i 
11 5 i 

inline.dat[r:4,c:1] = 10.8 
inline.dat[r:4,c:2] = 5.0 
inline.dat[r:0,c:1] = 10.0 
3

Per leggere un singolo valore da un file di dati si consideri la seguente funzione definita dall'utente:

at(file, row, col) = system(sprintf("awk -v row=%d -v col=%d 'NR == row {print $col}' %s", row, col, file)) 
file="delta-fps" ; row=2 ; col=2 
print at(file,row,col) 

Naturalmente, l'ingresso a awk deve essere sgombra da ignorati input/non valido (righe vuote, commenti, ecc) . Ad esempio:

at(file, row, col) = system(sprintf("grep -v '^#|^$' %s | awk -v row=%d -v col=%d 'NR == row {print $col}'", file, row, col)) 

Tuttavia, questa funzione non consente la lettura di alcun set di dati, è limitata ai file. Tuttavia, questa limitazione può essere superata controllando il carattere reindirizzamento '<' nell'argomento nome del file e sostituendo in modo sensibile (vedi l'operatore ternario):

at(file, row, col)=system(sprintf("%s | grep -v '^#\\|^$' | awk -v row=%d -v col=%d 'NR == row {print $col}'", (file[:1] eq '<') ? file[2:] :'cat '.file, row, col)) 

Un buon punto per definire una tale unzione potrebbe essere il tuo file .gnuplot init.

+0

Grazie per ciò, @Hannes - approccio pratico da tenere a mente. Saluti! – sdaau

Problemi correlati