全観測点の年平均降水量とその標準偏差を出力する

 #(1)観測点番号 平均値 標準偏差を求める(MonthlyAnnual/)
 #(2)観測点番号 経度 緯度を引き出す(STATION.DAT)
 #(3)観測点番号 経度 緯度 平均値 標準偏差を含むファイルを作る
 ################################################################################
 =begin
 まず基本的な考え方ですが、
 「観測点番号」をkeyにして、2つ(またはそれ以上)のデータ
 (今の場合は、STATION.DATと降水量データ)を結び付ける。
 これをするには、(2)より観測点番号をkeyにして、経度・緯度・高度・観測地点名
 をvalueとするような配列を作成し、そこにkeyとvalueを記憶させる。
 こうした配列は、普通の配列(Array)を使ってもできるが、
 連想配列(Hash)を使うと、もっと便利で計算速度も速い。
 こうして作ったmethodが、下の def station_datです。
 ここで、Hash(連想配列)名は、stationです。
 なお、緯度・経度の計算が正しくできるように、以前のものを変更し
 もう一つ別のddmmというmethodを作りました。
 =end
 ################################################################################
 #(2)観測点番号 経度 緯度を引き出す(STATION.DAT)
 def station_dat
   station = {}                         # station (Hash) の初期化
   station_file = "STATIONS_new.dat"        # STATIONS.DATを  station_new.dat
   open(station_file).each do |line|    # オープンし、各行読み取り
     array = line.chop.split
     if array.size == 8
       station_number = array[0]        # 観測点番号
       longitude = ddmm(array[2])       # 経度
       latitude = ddmm(array[1])        # 緯度
       altitude = array[3]              # 高度
       name = array[7]                  # 観測点名
       # station_numberをキーにして、観測点名、経度、緯度、高度の値を
       # 配列にしたものを、連想配列stationに格納
       station[station_number] = [name,longitude,latitude,altitude]
     end
   end
   station                              # 連想配列stationを戻す
 end
 # ddmmの表現の緯度経度の値をdegにする
 def ddmm(dm)
   x = dm.to_i                          # 元の値を整数化
   y = x / 100                          # 元の値を100で割る→度の値
   z = (x % 100).to_f/60.0   # 元の値を100で割ったときの余り(分に相当)を60で割る
   y + z                     # どの値(整数)に小数点以下を加えて戻りにする
 end
 ################################################################################
 class Array                #Arrayという配列を作る
   # 配列の全要素の平均を算出する
   def average         #averageは変数、初期化   
     inject(0.0){|r,i| r += i}/size.to_f      #sizeは要素の数
   end
   # 配列の全要素の分散を算出する
   def variance
     a = average
     inject(0.0){|r,i| r += (i - a)**2 }/size.to_f
   end
   # 配列の全要素の標準偏差を算出する
   def standard_deviation
     Math.sqrt(variance)
   end
 end
 ################################################################################
 #(1)観測点番号 平均値 標準偏差を求める(MonthlyAnnual/)
 # ある一つのファイルに対して、47年分の年降水量を読み取り、
 # 配列に格納した後、平均年降水量とその標準偏差を返す
  def mean_stdv(dir_file)
   n = 0                                # ヘッダを読み飛ばすための準備
   array = []                           # 各年の年降水量を格納する配列の初期化
   open(dir_file).each do |line|        # dir_fileをオープンし、各行を読み取る
     if n > 0                           # 2行目以降(ヘッダでない)なら
       v = line.chop.split              # lineから空白で分割して配列vを作成
       array << v[13].to_f              # 年降水量を配列arrayに格納
     end
     n += 1                             # 各行の読み取りと作業が済めば、行数加算
   end
 # 平均年降水量とその標準偏差を返す
   [array.average,array.standard_deviation]  #arrayは配列名、averageは上に定義したmethod
 end
 #############################################################################
 #(2)観測点番号 経度 緯度を引き出す(STATION.DAT)
 station = station_dat                  # 戻り値station: 連想配列
 ##########################################################################
 #(3)観測点番号 経度 緯度 平均値 標準偏差を含むファイルを作る
 # 全観測点の年平均降水量とその標準偏差を出力するファイル
 #out_file =  "c:/GIS/china/buchashuju" + "/" + "mean_annual_prec" + ".yr"
 out_file = "new_mean_annual_prec"
 out = open(out_file,"w")
 # ヘッダの出力
 #out.puts "st_num  name           longitude  latitude   altitude   mean   stdv" 
 dir = "MonthlyAnnual/"                 # 元ファイルのあるディレクトリ
 Dir.foreach(dir) do |file|
   if /mon$/ =~file
   # この観測点の47年分の年降水量から、平均年降水量とその標準偏差を計算
     mean,stdv = mean_stdv(dir + file)
     station_number = file[0..-5]       # 観測点番号
   # この観測点の結果の出力
     if station[station_number]         # 降水量観測点が全観測点記録中にあれば
     # 連想配列stationから、station_numberの経度緯度等の値を取り出す
       name,longitude,latitude,altitude = station[station_number]
       out.printf "%5s|%11.5f|%10.5f|%7.1f|%7.1f|%7.1f|%  s\n",station_number,longitude,latitude,altitude,mean,stdv,name
     end
   end
 end
 out.close                              # 出力ファイルのクローズ
結果は以下の通りです

QGISで改めでstationのベクタレイヤを作ります。
cat new_mean_annual_prec | v.in.ascii cat=1 out=new_mean_annual_prec x=2 y=3 col="cat integer, longitude double, latitude double, altitude varchar(10), mean double, stdv double, name varchar(30)"

今回はここまでになります。
お疲れ様でした。

タグ:

+ タグ編集
  • タグ:
最終更新:2010年11月09日 14:39
添付ファイル