MATLABでボートレース解析をする4番目の記事です。
この時期は台風とかの影響でボートレースの中止が多いですねー、という季節に書いてます。江戸川は台風が来ても来なくても波がザッパンザッパンしてますけど。
みんな大好きな払戻金も取り込まないとね。
1番目の記事でダウンロードができて、2番目の記事で出走表を読み込んで、3番目の記事で結果を読み込みましたが、配当はまだ取ってないですね。配当は3連単3,300円とかの払戻金のことです。
こっちの方が今までの出走表とかよりデータが少ないので簡単そうですね。場所+日付+レース番号から、配当一式にアクセスできればいいかな。
とりあえず 2019/8/1 - 8/3 の 3 日分をループにするとこんな感じ。
addpath('C:\work\boat')
%% テーブルを作ろう
T_div = table;
for n = datenum('20190801','YYYYmmDD'):datenum('20190803','YYYYmmDD')
%% レース結果の読み込み
fname = ['K',datestr(n,'YYmmDD'),'.TXT'];
fid = fopen(fname);
S = textscan(fid,'%s','delimiter','\n');
C = S{1};
fclose(fid);
%% BGN/ENDを探す
KBGN = find(contains(C,'BGN'));
KEND = find(contains(C,'END'));
%% BGN-END Loop
for BEloop = 1:length(KBGN)
%% BGN-ENDで切り取る
res = C(KBGN(BEloop)+1:KEND(BEloop)-1);
res(cellfun(@isempty,res)) = [];
% 場所
place = res{1}(1:3);
place(place == 12288) = [];
% 開催日
ymd = datestr(n,'YYYYmmDD');
start_idx = startsWith(res,'着');
x = find(start_idx)-1;
end_x = [x(2:end)-1;length(res)];
% ここからレースのループ
for Rloop = 1:length(x)
% レース番号
race = res(x(Rloop):end_x(Rloop));
R = regexp(race{1},'\d+R','match');
R = str2double(R{1}(1:end-1));
ix = contains(race,'単勝');
if any(ix)
z = regexp(race(ix),'\d+','match');
if length(z{1}) == 1 % 誰も買ってない場合の特払い70円 (2019/01/02 の 620行目の若松2Rとか)
win = NaN;
win_d = str2double(z{1}{1});
elseif isempty(z{1}) % 2013/01/14 の 児島7R に単勝が書いてない
win = NaN;
win_d = NaN;
else
win = str2double(z{1}{1});
win_d = str2double(z{1}{2});
end
end
ix = contains(race,'複勝');
if any(ix)
z = regexp(race(ix),'\d+','match');
if length(z{1}) == 1 % 特払い70円
show = [NaN NaN];
show_d = [70 70];
elseif length(z{1}) < 4 % 2019/8/1 の 383行目みたいに、複勝なのに1個しか書いてないのが結構ある。
show = [NaN NaN];
show_d = [NaN NaN];
else
show = [str2double(z{1}{1}),str2double(z{1}{3})];
show_d = [str2double(z{1}{2}),str2double(z{1}{4})];
end
end
ix = contains(race,'2連単');
if any(ix)
z = regexp(race(ix),'\d+','match');
if length(z{1}) <= 1 % 不成立
exacta = NaN;
exacta_d = NaN;
elseif length(z{1}) == 2 % 特払い70円
exacta = NaN;
exacta_d = str2double(z{1}{2});
else
exacta = str2double([z{1}{2},z{1}{3}]);
exacta_d = str2double(z{1}{4});
end
end
ix = contains(race,'2連複');
if any(ix)
z = regexp(race(ix),'\d+','match');
if length(z{1}) <= 1 % 不成立
quinella = NaN;
quinella_d = NaN;
elseif length(z{1}) == 2 % 特払い70円
quinella = NaN;
quinella_d = str2double(z{1}{2});
else
quinella = str2double([z{1}{2},z{1}{3}]);
quinella_d = str2double(z{1}{4});
end
end
ix = contains(race,'拡連複');
ix = ix | circshift(ix,1) | circshift(ix,2);
rx = race(ix);
if any(ix)
z = regexp(rx,'\d+','match');
if length(z{1}) <= 1 % 不成立
wide = [NaN NaN NaN];
wide_d = [NaN NaN NaN];
elseif ~all(ismember(rx{2}(1:3),'123456-')) % フォーマットがおかしい (2013/04/04 三国9Rとか)
wide = [NaN NaN NaN];
wide_d = [NaN NaN NaN];
else
wide = [str2double([z{1}{1},z{1}{2}]) str2double([z{2}{1},z{2}{2}]) str2double([z{3}{1},z{3}{2}])];
wide_d = [str2double(z{1}{3}) str2double(z{2}{3}) str2double(z{3}{3})];
end
end
ix = contains(race,'3連単');
if any(ix)
z = regexp(race(ix),'\d+','match');
if length(z{1}) <= 1 % 不成立
trifecta = NaN;
trifecta_d = NaN;
elseif length(z{1}) == 2 % 特払い70円
trifecta = NaN;
trifecta_d = str2double(z{1}{2});
else
trifecta = str2double([z{1}{2},z{1}{3},z{1}{4}]);
trifecta_d = str2double(z{1}{5});
end
end
ix = contains(race,'3連複');
if any(ix)
z = regexp(race(ix),'\d+','match');
if length(z{1}) <= 1 % 不成立
trio = NaN;
trio_d = NaN;
elseif length(z{1}) == 2 % 特払い70円
trio = NaN;
trio_d = str2double(z{1}{2});
else
trio = str2double([z{1}{2},z{1}{3},z{1}{4}]);
trio_d = str2double(z{1}{5});
end
T_div(end+1,:) = {place,ymd,R,win,win_d,show,show_d,exacta,exacta_d,quinella,quinella_d,wide,wide_d,trifecta,trifecta_d,trio,trio_d};
end
end
end
end
T_div.Properties.VariableNames = {'Place','YYYYMMDD','R','win','win_d','show','show_d','exacta','exacta_d','quinella','quinella_d','wide','wide_d','trifecta','trifecta_d','trio','trio_d'};
% 数種類に分類できる項目はカテゴリカル。
T_div.win = categorical(T_div.win);
T_div.show = categorical(T_div.show);
T_div.quinella = categorical(T_div.quinella);
T_div.wide = categorical(T_div.wide);
T_div.exacta = categorical(T_div.exacta);
T_div.trifecta = categorical(T_div.trifecta);
T_div.trio = categorical(T_div.trio);
例外が多すぎてプログラムが長くなってしまった。。。
ただ、実行時間は1秒未満でした。
ボートレース豆知識
不成立は、フライングとかの失格が多くて、賭けが成り立たなくなったときに不成立になります。3艇失格なら3連複が不成立、4艇失格なら複勝・2連複・拡連複・3連複・3連単が不成立かな。
特払いは、当たりの結果を誰も買ってないときに、購入者全員に金額の7割を払い戻す制度です。例えば単勝1番の舟券を1,000円持ってたのに6番が1着になってしまった場合でも、世界中の誰しもが6番の単勝を買ってない場合は、1番の舟券でも700円返ってきます。(=みんな一律に損をするけど、ハズレなのにお金が返ってくるので得した気になれる。)
データはちゃんと取れたのかな
コマンドウィンドウで見てみよう。
>> T_div
T_div =
480×17 table
Place YYYYMMDD R win win_d show show_d exacta exacta_d quinella quinella_d wide wide_d trifecta trifecta_d trio trio_d
_______ __________ __ ___________ _____ ________________________ ____________ ______ ________ ________ __________ __________ ____________________ ________ __________ ____ ______
'唐津' '20190801' 1 1 100 1 2 100 110 12 430 12 330 12 14 24 180 240 760 124 1400 124 820
'唐津' '20190801' 2 1 110 1 3 120 190 13 450 13 380 13 12 23 140 100 160 132 660 123 170
'唐津' '20190801' 3 3 160 3 2 120 210 32 680 23 570 23 13 12 130 110 150 321 1380 123 170
'唐津' '20190801' 4 3 140 3 5 170 290 35 600 35 640 35 23 25 160 680 970 352 9420 235 3000
'唐津' '20190801' 5 1 190 1 2 190 660 12 800 12 730 12 15 25 250 950 2000 125 13880 125 4860
'唐津' '20190801' 6 6 900 6 4 520 490 64 3020 46 1300 46 56 45 250 1030 1480 645 28120 456 4840
'唐津' '20190801' 7 2 490 2 3 210 150 23 1140 23 600 23 25 35 340 640 680 235 9340 235 2720
'唐津' '20190801' 8 3 150 3 6 100 260 36 350 36 380 36 23 26 180 190 430 362 1080 236 430
'唐津' '20190801' 9 1 110 1 2 110 190 12 250 12 250 12 13 23 120 140 200 123 590 123 230
'唐津' '20190801' 10 3 730 3 4 600 1140 34 5370 34 2530 34 35 45 670 640 1100 345 21230 345 3900
'唐津' '20190801' 11 2 190 2 1 100 100 21 380 12 150 12 24 14 120 250 150 214 1260 124 340
'唐津' '20190801' 12 2 720 2 1 100 100 21 860 12 170 12 26 16 140 610 1100 216 11640 126 2460
'福岡' '20190801' 1 1 150 1 2 110 430 12 160 12 190 12 16 26 150 270 1280 126 1680 126 690
'福岡' '20190801' 2 1 230 1 3 130 100 13 820 13 360 13 15 35 120 1760 320 135 10380 135 1790
'福岡' '20190801' 3 1 330 1 4 280 390 14 510 14 370 14 16 46 140 540 380 146 1320 146 520
'福岡' '20190801' 4 2 2770 <undefined> <undefined> NaN NaN 26 11130 26 4920 26 12 16 620 460 200 261 36510 126 1940
'福岡' '20190801' 5 3 170 3 4 120 150 34 560 34 310 34 35 45 200 260 430 345 1290 345 510
'福岡' '20190801' 6 1 360 1 2 130 130 12 750 12 420 12 13 23 280 160 250 123 2070 123 550
'福岡' '20190801' 7 1 400 1 4 120 100 14 390 14 280 14 13 34 250 840 840 143 2820 134 900
'福岡' '20190801' 8 1 100 1 3 100 110 13 150 13 110 13 15 35 100 450 300 135 800 135 610
'福岡' '20190801' 9 2 620 2 4 120 210 24 1880 24 950 24 25 45 160 560 910 245 5350 245 1220
'福岡' '20190801' 10 2 330 2 3 130 100 23 850 23 550 23 12 13 200 160 110 231 1920 123 240
'福岡' '20190801' 11 1 720 1 2 100 140 12 300 12 140 12 15 25 190 230 420 125 1570 125 520
'福岡' '20190801' 12 1 120 1 2 100 100 12 310 12 310 12 15 25 130 200 410 125 1860 125 900
大丈夫そう!
win が単勝で当たりのボート番号、win_d が単勝の払戻金です。その他 _d を付けたのを金額にしました。
欠けたデータは何なのだ。
Qiita だと白くて目立つ Undefined とか NaN とかがあるけどなんだろう。
元のファイルで 2019/8/1 の福岡 4R を見てみよう。
4R 予 選 H1800m 晴 風 北 2m 波 3cm
着 艇 登番 選 手 名 モーター ボート 展示 進入 スタートタイミンク レースタイム 差し
-------------------------------------------------------------------------------
01 2 3315 広 瀬 聖 仁 23 171 6.96 2 0.21 1.53.7
02 6 4573 佐 藤 翼 65 112 6.90 6 0.05 1.56.0
03 1 3870 寺 嶋 雄 21 120 6.92 1 0.11 1.57.0
04 3 3977 山 本 兼 士 51 123 6.96 3 0.15 1.57.3
05 5 3658 阪 本 聖 秀 61 165 6.89 5 0.12 . .
06 4 4736 高 倉 和 士 55 161 6.94 4 0.08 . .
単勝 2 2770
複勝 6 120
2連単 2-6 11130 人気 24
2連複 2-6 4920 人気 13
拡連複 2-6 620 人気 11
1-2 460 人気 7
1-6 200 人気 2
3連単 2-6-1 36510 人気 86
3連複 1-2-6 1940 人気 8
複勝は2と6が当たりなのに、6しか書いてない!みたいなダメなデータが結構ある。。(なんとなく福岡に多い気がする。)
でもデータはその他にもたくさんあるのでプログラムで除外しちゃえばいいか、、という方針で、こういうのを見つけたら NaN とかにしておきましょう。(些細なことは気にしない。)
払戻金データも取れました!
長くなったからここまでにするけど、次こそはデータの整理かなあ。
また今度書くので、気になる人は「いいね」を押してね。(いいね病)