RubyとRで競馬分析

ダウンロードしたデータのインデックス情報を作成

ダウンロードした.datファイルは、JVLinkの出力を順番に記録したものなので、格納されているデータの順番はバラバラです。
そこで、私はRubyスクリプト「DataLab_Index.rb」で検索用の情報を作って利用しています。

Rubyスクリプト「DataLab_Index.rb」、Downloadフォルダ内の各.datファイルに対応した.idxファイルを出力します。
この.idxファイルは、JRA-VAN SDKに含まれているJV-Data仕様書でレコードのキーとされている情報で検索するための情報です。
.datファイル内に同じキーの情報があった場合、作成日時が新しいデータが優先されます。
また、作成日時が同じか不明な場合は、最近取得したデータが優先されます。

.idxファイルは、「キー情報」+「,」+「データのある位置(先頭からのバイト数。10文字)」+「改行」の形式になっています。つまり、同じ.idxファイル内では、1行の長さが固定されています。また、一応、キー情報で昇順にソートされた形で格納されています。

このスクリプトは、古い.idxファイルがあっても無視して、各.datファイルを頭から調べ直しています。
.datファイルは末尾に追記されていくだけのファイルなので、既存の.idxファイルを再利用すればもっと効率がよく作成できるでしょう。
とりあえず、頻繁にする作業でもないので問題になっていません。

使い方

(1) Downloadフォルダ内に.datファイルが存在する状態でスクリプトを実行します。オプションはありません。

>ruby DataLab_Index.rb

(2) 進行状況が表示されます。括弧内の数字は、「(有効データ数/全データ数)」です。

DataLab_Index.rb

#JRA-VANからダウンロードしたデータのインデックスを作る

#DATファイルのフォーマット定義。作成日時(位置,サイズ)、インデックス@(位置,サイズ)…
DATFormat = { "TK" => [ 3, 8, 11, 16 ], \
              "RA" => [ 3, 8, 11, 16 ], \
              "SE" => [ 3, 8, 11, 16, 28, 12 ],
              "HR" => [ 3, 8, 11, 16 ], \
              "H1" => [ 3, 8, 11, 16 ], \
              "H6" => [ 3, 8, 11, 16 ], \
              "O1" => [ 3, 8, 11, 16 ], \
              "O2" => [ 3, 8, 11, 16 ], \
              "O3" => [ 3, 8, 11, 16 ], \
              "O4" => [ 3, 8, 11, 16 ], \
              "O5" => [ 3, 8, 11, 16 ], \
              "O6" => [ 3, 8, 11, 16 ], \
              "UM" => [ 3, 8, 11, 10 ], \
              "KS" => [ 3, 8, 11,  5 ], \
              "CH" => [ 3, 8, 11,  5 ], \
              "BR" => [ 3, 8, 11,  6 ], \
              "BN" => [ 3, 8, 11,  6 ], \
              "HN" => [ 3, 8, 11,  8 ], \
              "SK" => [ 3, 8, 11, 10 ], \
              "RC" => [ 3, 8, 11, 21, 93, 8 ], \
              "HC" => [ 3, 8, 11, 23 ], \
              "WH" => [ 3, 8, 11, 16 ], \
              "WE" => [ 3, 8, 11, 23 ], \
              "AV" => [ 3, 8, 11, 16, 35, 2 ], \
              "JC" => [ 3, 8, 11, 26 ], \
              "DM" => [ 3, 8, 11, 16 ], \
              "YS" => [ 3, 8, 11, 14 ], \
              "TC" => [ 3, 8, 11, 16 ], \
              "CC" => [ 3, 8, 11, 16 ] }

#Downloadフォルダ内の.datファイルを列挙する
Dir.glob('Download/*.dat').each { |name|
  if FileTest.file?(name) then
    recodeid = File.basename(name)[0,2].upcase
    if DATFormat.key?(recodeid) then
      fmt = DATFormat[recodeid]

      #DATファイルを読み込む
      dat_count = 0
      print "[", name, "]読み込み中..."
      index = Hash.new([0, "00000000"])
      open(name, "rb") { |datfile|
        position = 0
        datfile.each { |line|
          line_date  = line[fmt[0],fmt[1]]
          line_index = line[fmt[2],fmt[3]]
          if fmt.size > 5 then
            line_index += line[fmt[4],fmt[5]]
          end

          #インデックス情報更新
          old_index = index[line_index]
          if old_index[1] < line_date then
            index[line_index] = [position, line_date]
          end

          position = datfile.pos
          dat_count = dat_count + 1
        }
      }
      print "終了\n"

      #インデックスをソート
      index_keys = index.keys
      index_keys.sort!

      #インデックスファイルを書き込む
      idxname = 'Download/' + recodeid + ".idx"
      print "[", idxname, "]書き込み中..."
      open(idxname, "w") { |idxfile|
        index_keys.each { |key|
          idxfile.printf("%s,%010d\n", key, index[key][0])
        }
      }
      print "終了(", index.size, "/", dat_count, ")\n" 
    end
  end
}

注意

Windows版Rubyでは、2GBを超えるファイルで、File.sizeやIO#posが正しく動作しないようです。
そのため、このスクリプトはサイズが2GBを超える.datファイルに対して正常に動作しません。
H1.datファイルのサイズが2GBを超えているような場合は、「"H1" => [ 3, 8, 11, 16 ], \」の行を削除(またはコメントアウト)してください。(その場合は、H1のインデックスファイルが作成されません。)


Creative Commons License
この作品は、クリエイティブ・コモンズ・ライセンスの下でライセンスされています。

(C) 2006-2008 NARITA, Takuro
E-Mail:narita@a1.mbn.or.jp