1

次のようなデータファイルがあります。

"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

gnuplot を使用して、データの各ブロックを他のブロックとは別にプロットしたいと考えています。この目的で使用しているコードは次のとおりです。

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)

それは正常に動作します。

ここで、各データ ブロックで最大の y 値を持つ点 (x,y) を特定し、このデータ ブロックに対応する曲線と同じ色のマーカーでプロットしたいと思います。使ってみた

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

前のコードの後ですが、これはすべてのブロックを含む2番目の列全体で最大値を見つけるようです.

2 番目にやりたいことは、データ ブロックごとに、最大値のマーカーとは形状が異なるが同じ色 (曲線の色) のマーカーを使用して、そのブロックの最初の行をプロットすることです。

これらの 2 つのタスクは、gnuplot と曲線をプロットする方法 (列ヘッダー) で可能ですか?

4

1 に答える 1

6

これは可能です。stats コマンドを広範囲に使用し、一時ファイルを使用します。gnuplot 5 では、名前付きデータ ブロックを使用してメモリ内に一時ファイルを作成できます (「参考文献」を参照help datablocks)。

さらに、プロット コマンドは大部分が反復的であるため、プロットを構文に使用できます。

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

これにより、変数 in に 0 ~ 2 の値を使用して plot コマンドが繰り返されます (提供されたコマンドは 4 つのデータ ブロックを使用しますが、提供されたデータ ファイルには 3 つしかありません)。

次のスクリプトは、目的を達成します。

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

これにより(提供されたデータファイルを使用して)生成されます

ここに画像の説明を入力

曲線 0 と 2 の場合、最初の点と最大点が同じであるため、シンボルが隠されています。

これを再プロットしますが、仕様を変更して最初のポイント マーカーを 0.1 だけ上に移動すると、必要な場所に表示されることがわかります。

ここに画像の説明を入力


このセクションは長くなりますが、コードを分解して、可能な限り行ごとに詳しく説明します。ここには微妙なことがいくつかあるからです。

最初の 2 行

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

ファイルに対して stats コマンドを実行します。名前付きの列ヘッダーのため、using 仕様を指定しないと stats 関数が失敗するため、仕様を指定しますu 1:2。このnooutputオプションは、stats コマンドに結果を取得するよう指示しますが、結果は出力しません。ここでは、ブロックの数を取得することだけに関心があります。これを変数ブロックに保存します(後の統計コマンドが変数を上書きするため)。名前付きプレフィックスを指定することもできましたが、それによってすべての変数が保存され、その理由はありません。これら 2 つのコマンドの代わりに、正確に 3 つのブロックの場合、以下のすべてのブロックの出現を値 3 に置き換えることができますが、この方法ではブロックの数はハードコーディングされません。

次に、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) 
}

最も難しく、ほとんどの魔法が発生する場所です。2 つのデータブロックを持つ一時ファイルを作成します。1 つ目は最大値で、2 つ目は最初の値です。メモリ内の最初のポイントを計算し、その最初のデータ ブロックを作成した後に追加します。x 座標と y 座標は、スペースで区切られた文字列変数に格納されます。

すべてのデータ ブロックを繰り返し処理し、統計コマンドを計算します。表現

(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 つの文字列変数を再割り当てします。これを行うには、最初にポイントが一連の最初のものであるかどうかを確認します (0 の値はヘッダー行に対応するため、$0 の値は 1 になります)。そうである場合は、最初の列の値を追加して文字列変数を再構築します (y 座標についても同様です)。それ以外の場合は、同じものを変数に再割り当てするだけです。最後に、最初の列の値を返します。このように式を括弧で囲んでコンマで区切ると、各式が順番に評価され、最終的な値が返されます。

したがって、stats コマンドは以前と同じように動作します。

stats 'file' index i u 1:2 nooutput

しかし、この小さなトリックにより、最初の行の値を読み取って、入力時に保存することができます。最後に、最大の y 値を持つポイントが出力されます。これは一時ファイルに入ります。

ここで、最初のポイントを新しいデータブロックとして一時ファイルに追加する必要があります。最初に 2 行の空白行を出力し、次に実行中のブロックの数を繰り返し処理します。

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

ブロックごとに (ここで、i はブロックの番号です)。word 関数は、文字列変数をスペースで区切られた単語のリストとして扱い、要求された単語を抜き出します。この時点で、文字列変数は次のようになります

 0.000000 0.000000 8.000000 # first_x
 0.780000 0.876000 2.230500 # first_y

最後に、これを発行set printして、コンソールに印刷するための印刷コマンドを復元します。次のような一時ファイルを作成しました

0.000000 0.780000
16.000000 0.950000
8.000000 2.230500


0.000000 0.780000
0.000000 0.876000
8.000000 2.230500

ここで、最初のデータブロックは最大の y 値を持つポイントであり、2 番目のデータブロックは最初のポイントです。

最後に、次のようにプロットします

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

この最初の部分は前と同じですが、ブロック数をハードコーディングする代わりに、ブロック変数が使用されています。

次に、一時ファイルをインデックス 0 とインデックス 1 で 2 回プロットします。線の色は、行番号 (この場合は 0 から 2) に基づいて可変です。1 を追加して、通常 0 ベースの行番号を強制的に 1 ~ 3 にします。これは、以前のデータブロックに対応します。ポイントでプロットし、プロットしているデータブロックに基づいてポイント タイプを選択します。この場合、塗りつぶされた円 (最大値の場合) または塗りつぶされた三角形 (最初の点の場合) のいずれかです。

于 2016-04-16T22:51:21.830 に答える