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人のデータが取れました!
出走表を取り込んで、選手ごとにデータを分別できました。
結果のデータも取り込んだりテーブルの操作もしなきゃダメですけど、長くなったのでとりあえずここまで。
続きが早く知りたい人は「いいね」で教えてね。(いいね至上主義)