14
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

MATLABで競艇の解析を始めよう(大量の出走表ファイルからデータを読み込み)

Last updated at Posted at 2019-08-08

MATLABでボートレース解析をする2番目の記事です。

[最初の記事] (https://qiita.com/teruqii/items/11c21882613db088e339) の通りにやると C:\work\boat フォルダにファイルができましたよね。

とりあえず自分は試しに2005年から2019年まで15年分取ってみましたが、時間はかかるし、1.75GB(ファイル数 10000 超)のテキストファイルでフォルダーが埋まってしまうし、結局こんなに使わないし、、、ということで、こんなに取らなくてもいいね。(捨てよう。。。)

ボートレース豆知識

 どの期間のデータを取ればよさそうかと言うと、2012年4月27日前後で持ちペラ制度っていう自前のプロペラを使うことがなくなって、2019年現在まで抽選ボート+抽選プロペラでレースをやってるので、2012年の5月以降のデータを使うと統一されたルールのデータセットになります。むしろ、もう少し後の落ち着いた頃のデータでもいいかもね。

※ 前後って書いてるのは、「4/27以降に初日を迎えるレース場~」とかの理由。

そもそもダウンロードしたのはどんなファイルなんだっけ。

試しに 2019/8/1 の B の名前の付いたファイル(出走表)を空けてみるとこんな感じ。

STARTB
23BBGN
ボートレース唐 津  8月 1日 ヴィーナスシリーズ第 第 4日
*** 番組表 ***
ヴィーナスシリーズ第7戦RKBラジオ杯      
第 4日 2019年 8月 1日 ボートレース唐 津
-内容については主催者発行のものと照合して下さい-
1R 一  般   H1800m 電話投票締切予定08:55
-------------------------------------------------------------------------------
艇 選手 選手 年 支 体級 全国 当地 モーター ボート 今節成績 早
番 登番 名 齢 部 重別 勝率 2率 勝率 2率 NO 2率 NO 2率 123456見
-------------------------------------------------------------------------------
1 4627藤原菜希33東京46A1 6.47 47.50 5.28 32.00 63 36.60 76 41.46 2S221 12
2 5019柴田百恵19静岡45B1 2.13 1.33 0.00 0.00 17 41.78 45 22.50 S44 4 7
3 4758富樫麗加29東京51B1 5.08 26.61 6.06 41.94 65 34.25 35 30.86 4 3664 5
4 4947間庭菜摘26福岡51B1 2.66 10.39 1.69 2.86 18 33.33 72 25.00 5 636 6
5 4994山本梨菜21佐賀48B1 2.75 3.45 1.77 0.00 25 34.38 65 25.33 264 4 6
6 5057上田紗奈23大阪45B2 1.66 1.00 0.00 0.00 33 29.05 55 32.91 6 656 5
 2R 一  般   H1800m 電話投票締切予定09:24
-------------------------------------------------------------------------------
艇 選手 選手 年 支 体級 全国 当地 モーター ボート 今節成績 早
番 登番 名 齢 部 重別 勝率 2率 勝率 2率 NO 2率 NO 2率 123456見
-------------------------------------------------------------------------------
1 4885大山千広23福岡47A1 6.73 46.94 3.92 15.38 26 42.27 66 29.73 31432 12
2 4556竹井奈美29福岡47A1 6.44 45.80 7.05 53.85 46 26.00 75 40.48 3S453 6
3 4938小芦るり21佐賀51B1 4.62 31.00 3.25 15.38 23 31.31 34 31.65 432 55 8
4 4923末武里奈27山口47B1 3.29 12.70 1.33 0.00 16 37.44 50 31.08 5 642 7
5 4997濱崎寿里26埼玉52B2 1.38 3.85 0.00 0.00 11 38.53 47 26.92 6 666 7
6 5013山下夏鈴22三重44B1 2.47 6.38 2.00 5.88 53 30.92 79 39.74 366 6 6
...
...
この間に、まだまだたくさんある。
...
...
23BEND
22BBGN
ボートレース福 岡  8月 1日 誰が勝っても福岡初優 第 1日
...
ここから別の会場の情報。
...

この 1R だと断然 1-3-4 の3連単を買いたくなるのはさておき、今回は試しに個人の単位でテーブルをまとめてみましょう。

MATLABでデータを取り込む

ボートレースは同じ日に同じ人が2回出てくることもあって、時々同じ行が出てくるので、データをまとめる場合は要注意ポイントです。MATLAB だと unique 関数を使えば同じデータは1つにまとまりますね。(超便利!)

あとは、セル配列とか構造体とかあるけど、こういうフォーマットであればテーブルデータが解析に向いてるデータ形式です。とりあえず、こんなプログラムで 2019/8/1 の分だけでも取ってみよう。

ix = datenum('20190801','YYYYmmDD');
fname = ['B',datestr(ix,'YYmmDD'),'.TXT'];

fid = fopen(fname);
S = textscan(fid,'%s','delimiter','\n');
B = S{1};
fclose(fid);
B = B(~cellfun(@isempty,(regexp(B,'^\d \d+'))));
Personal = cellfun(@scanB,B,'Unif',0);
Personal = unique(cell2mat(Personal),'rows');
T_Person = array2table(Personal,'VariableNames',{'NameNo','Age','Weight','Class','A_WinRate','A_DoubleWinRate','L_WinRate','L_DoubleWinRate','Motor','M_DoubleWinRate','Boat','B_DoubleWinRate'});


function sc = scanB(txt)

NAME = str2double(txt(3:6));
MOTOR = str2double(txt(41:43));
BOAT = str2double(txt(50:52));
AGE = str2double(txt(11:12));
WEIGHT = str2double(txt(15:16));
if strcmp(txt(17:18),'A1')
    CLASS = 1;
elseif strcmp(txt(17:18),'A2')
    CLASS = 2;
elseif strcmp(txt(17:18),'B1')
    CLASS = 3;
else
    CLASS = 4;
end
A_WINRATE = str2double(txt(19:23));
A_DOUBLEWINRATE = str2double(txt(24:29));
L_WINRATE = str2double(txt(30:34));
L_DOUBLEWINRATE = str2double(txt(35:40));
M_DOUBLEWINRATE = str2double(txt(44:49));
B_DOUBLEWINRATE = str2double(txt(53:58));
sc = [NAME,AGE,WEIGHT,CLASS,A_WINRATE,A_DOUBLEWINRATE,L_WINRATE,L_DOUBLEWINRATE,MOTOR,M_DOUBLEWINRATE,BOAT,B_DOUBLEWINRATE];
end

 サブ関数 scanB にまとめてしまったけど、3~6文字目に名前があるとか文字数が決まってる場合は char 型の配列で txt(3:6) とか取ったほうがよくて、文字数じゃない場合は textscan とかしたほうが融通が効きます。

このスクリプトを実行すると、T_Person っていうテーブル変数ができて、どんな感じかな。。

>> T_Person

T_Person =

  586×12 table

    NameNo    Age    Weight    Class    A_WinRate    A_DoubleWinRate    L_WinRate    L_DoubleWinRate    Motor    M_DoubleWinRate    Boat    B_DoubleWinRate
    ______    ___    ______    _____    _________    _______________    _________    _______________    _____    _______________    ____    _______________

     2878     61       55        2        5.59            38.46           6.06            42.55          32           28.25          28          35.03     
     2903     60       50        3        4.84               25           4.88               25          68           27.94          42          26.15     
     3020     59       51        3        3.93            20.48           4.57            22.22          32            7.41          38          45.16     
     3036     61       56        3        4.59            20.41           4.11            21.05          10           31.25          32          30.23     
     3051     56       53        3        4.53               25           4.23            19.23          62           42.56          55           32.7     
...
...

8/1 に出場してる 586人分のデータが取れてる!よさそう!

名前は解析に使いやすそうな NameNo だけ取って(藤原菜希選手=4627)、今節成績とか早見とかは解析に不要そう(=別のデータで出てくる)なので取りませんでした。A1, A2, B1, B2 のクラスも解析しにくそうだったので、A1 → 1、B2 → 4 に変換しました。

あとは For文 を書けばいいね。

8/1 から 8/3 だったらこんな感じ。

for ix = datenum('20190801','YYYYmmDD'):datenum('20190803','YYYYmmDD')   % ここを修正
    fname = ['B',datestr(ix,'YYmmDD'),'.TXT'];
    
    fid = fopen(fname);
    S = textscan(fid,'%s','delimiter','\n');
    B = S{1};
    fclose(fid);
    B = B(~cellfun(@isempty,(regexp(B,'^\d \d+'))));
    Personal = cellfun(@scanB,B,'Unif',0);
    Personal = unique(cell2mat(Personal),'rows');
    T_Person = array2table(Personal,'VariableNames',{'NameNo','Age','Weight','Class','A_WinRate','A_DoubleWinRate','L_WinRate','L_DoubleWinRate','Motor','M_DoubleWinRate','Boat','B_DoubleWinRate'});
end                                                                       % ここもセットで追記

function sc = scanB(txt)

NAME = str2double(txt(3:6));
MOTOR = str2double(txt(41:43));
BOAT = str2double(txt(50:52));
AGE = str2double(txt(11:12));
WEIGHT = str2double(txt(15:16));
if strcmp(txt(17:18),'A1')
    CLASS = 1;
elseif strcmp(txt(17:18),'A2')
    CLASS = 2;
elseif strcmp(txt(17:18),'B1')
    CLASS = 3;
else
    CLASS = 4;
end
A_WINRATE = str2double(txt(19:23));
A_DOUBLEWINRATE = str2double(txt(24:29));
L_WINRATE = str2double(txt(30:34));
L_DOUBLEWINRATE = str2double(txt(35:40));
M_DOUBLEWINRATE = str2double(txt(44:49));
B_DOUBLEWINRATE = str2double(txt(53:58));
sc = [NAME,AGE,WEIGHT,CLASS,...
    A_WINRATE,A_DOUBLEWINRATE,...
    L_WINRATE,L_DOUBLEWINRATE,MOTOR,M_DOUBLEWINRATE,...
    BOAT,B_DOUBLEWINRATE];
end

3日分のファイルから、622人のデータが取れました!

出走表を取り込んで、選手ごとにデータを分別できました。

結果のデータも取り込んだりテーブルの操作もしなきゃダメですけど、長くなったのでとりあえずここまで。
続きが早く知りたい人は「いいね」で教えてね。(いいね至上主義)

→ 3番目の記事
→ 4番目の記事 を書いたよ。

14
9
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?