やりたいこと
GRASSのr.univarが出力する,あるラスターデータの最大値や最小値を使ってラスター演算(r.mapcalc)をする
方法
ターミナルユーザーであれば,awkを使うことで,問題なく処理をすることができる
あるラスターデータを "dummy" とする。
r.univarを実行すると,以下のように出力される。
$r.univar map=dummy total null and non-null cells: 5157441 total null cells: 0 Of the non-null cells: ---------------------- n: 5157441 minimum: 0 maximum: 1 range: 1 mean: 0.0155387 mean of absolute values: 0.0155387 standard deviation: 0.123682 variance: 0.0152973 variation coefficient: 795.961 % sum: 80140
出力結果を見てみると,最小値は7行目,最大値は8行目のそれぞれ2列目に出力される。
ということで,最大値のみを取り出すには次のようにする。
NRで取り出す行数を,\$で列数を指定している。
r.univar map=dummy | awk '{if(NR==8){printf(\$2); printf(RS)}}'
最小値の場合にはNRの部分を7にすればよい。
r.univar map=dummy | awk '{if(NR==7){printf(\$2); printf(RS)}}'
さて,値自体は取り出すことができたので,次はラスター演算(r.mapcalc)で使えるようにしたい。
単純に,取り出した値をシェル変数に代入する。
試しに,割合(%)を示すデータdummy2を作成してみる。
i=`r.univar map=dummy | awk '{if(NR==8){printf(\$2); printf(RS)}}'` r.mapcalc "dummy2=(dummy/$i)*100"
これ以外にも方法はあると思う。単純にr.mapcalcの構文内に`r.univar map=dummy | awk '{if(NR==8){printf(\$2); printf(RS)}}'`を入れるだけでも良いかもしれない。
応用
次のようにすることで,r.univarの出力結果をテキストファイルに1行で書き出すことができる。
r.univar map=dummy | awk '{ if(NR==6){printf(\$2); printf(FS);} else if(NR==7){printf(\$2); printf(FS);} else if(NR==8){printf(\$2); printf(FS);} else if(NR==9){printf(\$2); printf(FS);} else if(NR==10){printf(\$2); printf(FS);} else if(NR==11){printf(\$5); printf(FS);} else if(NR==12){printf(\$3); printf(FS);} else if(NR==13){printf(\$2); printf(FS);} else if(NR==14){printf(\$3); printf(FS);} else if(NR==15){printf(\$2); printf(FS);}} END{printf(RS)}' > dummy2
これは非常に使える方法で,例えば沢山のラスターデータの統計量をひとつのテキストファイルにまとめることができる。
結果を書き込むファイルを "result.txt" とする
#結果を書き込むファイルを作成し,ヘッダを書き込む echo "n minimum maximum range mean MeanOfAbsoluteValues StandardDeviation Variance VariationCcoefficient Sum" > result.txt #マップセット内のラスターデータすべてのr.univarの出力をresult.txtに書きこむ for i in `g.mlist rast` do r.univar map=\$i | awk \'{if(NR==6){printf(\$2); printf(FS);} else if(NR==7){printf(\$2); printf(FS);} else if(NR==8){printf(\$2); printf(FS);} else if(NR==9){printf(\$2); printf(FS);} else if(NR==10){printf(\$2); printf(FS);} else if(NR==11){printf(\$5); printf(FS);} else if(NR==12){printf(\$3); printf(FS);} else if(NR==13){printf(\$2); printf(FS);} else if(NR==14){printf(\$3); printf(FS);} else if(NR==15){printf(\$2); printf(FS);}} END{printf(RS)}' >> result.txt done
GRASSでもこの辺りを充実してくれると嬉しいのですが...
2 件のコメント:
awk の話が出ていたので懐かしく
書き出しは以下のようにすると良いかも知れません。最後の END { printf FS } は不要でしょう。
/minimum:/, /sum:/ {
printf ($NF=="%" ? $(NF-1) : $NF) FS
}
ご指摘ありがとうございます。
私自身,awkはまだ使いこなすレベルに達していないので,今後の参考にさせていただきます。
なお,一部bloggerのアドオンの関係で表示がおかしくなっています。
暇を見て修正します。
コメントを投稿