1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

WinningPost10の馬券王データを効率よく集めるためのツールを作成

Posted at

はじめに

今回はWinningPost10の馬券王で遊ぶときに使うツールを作成しました。馬券王の結果を簡単に入力し、記録した結果の勝率、連帯率、複勝率を表示させます。

馬券王で遊んでいると、「この馬はよく来るな」「この馬は来ないな」と何となく傾向がつかめてきます。それをしっかりデータとして記録し、馬券購入をしていきたいと考えたので作ってみました。

事前知識

一応、以下で紹介したOCRの技術を使っています。

データ入力部分

まず、データを入力する場所についてです
以下のような表をDataFrameとして入力します。

1着 2着 3着 horse_nam
False True False リバティアイランド
False False False ヒカリデュール
True False False イクイノックス
False False False ゼニヤッタ
False False True エエヤン
False False False カンパニー

実際のUIだとこんな感じです。
image.png

これを入力として、競馬でよく見る[0-0-0-0]の形式に変換していきます。
変換した後、既存データに加算を行い、勝率などの割合を計算して、データを保存。

def update_data(df, race_name):
    # 既存のデータを読み込む
    df_race_data = pd.read_csv(f"race_data/{race_name}.csv")
    
    # 既存の成績データに基づいて追加データを更新
    for _, row in df.iterrows():
        horse_name = row['horse_name']
        # 馬名が既に存在する場合、成績を加算
        if horse_name in df_race_data['horse_name'].values:
            idx = df_race_data[df_race_data['horse_name'] == horse_name].index[0]
            df_race_data.loc[idx, '1'] += int(row['1着'])
            df_race_data.loc[idx, '2'] += int(row['2着'])
            df_race_data.loc[idx, '3'] += int(row['3着'])
            df_race_data.loc[idx, '4-'] += int(not row['1着'] and not row['2着'] and not row['3着'])
        else:
            # 馬名が存在しない場合、新たに行を追加
            new_row = pd.DataFrame([{'horse_name': horse_name, '1': int(row['1着']), '2': int(row['2着']), '3': int(row['3着']), '4-': int(not row['1着'] and not row['2着'] and not row['3着'])}])
            df_race_data = pd.concat([df_race_data, new_row], ignore_index=True)
            
    # 勝率、連帯率、複勝率を計算して成績データに追加
    df_race_data['勝率'] = df_race_data['1'] / (df_race_data[['1', '2', '3', '4-']].sum(axis=1))
    df_race_data['連帯率'] = (df_race_data['1'] + df_race_data['2']) / (df_race_data[['1', '2', '3', '4-']].sum(axis=1))
    df_race_data['複勝率'] = (df_race_data['1'] + df_race_data['2'] + df_race_data['3']) / (df_race_data[['1', '2', '3', '4-']].sum(axis=1))

    # データを保存
    df_race_data.to_csv(f"race_data/{race_name}.csv", index=False)
    
    return df_race_data

ここまで終わればほぼ完成したようなものです。

データの表示

ここでは入力された馬の名前から、該当するもののみを表示させます。

def view_data(horse_list, race_name):
    # レースデータを読み込む
    df_race_data = pd.read_csv(f"race_data/{race_name}.csv")
    
    # 指定された馬名の成績のみをフィルタリングして表示
    filtered_results = df_race_data[df_race_data['horse_name'].isin(horse_list)]
    
    return filtered_results

セッションで保存しておく用のクラスを定義

最近はstreamlitでデータを保存しておくためにクラスを定義し、そのオブジェクトをst.sessions_stateで保存しています。

class RaceData:
    def __init__(self):
        # 初期化
        self.race_list = None
        self.race_name = None
        self.img = None
        self.ocr_texts = None
        self.df_ocr = None
        self.df_view = None
        self.df_log = None
        self.edit_df = None
        
    def select_race(self):
        self.race_list = pd.read_csv("C:/Users/tashi/Programming/wipo10/bakeno/race_names.csv")["race_name"].to_list()
        self.race_name = st.selectbox("登録するレースを選択", self.race_list)
    
    
    def upload_img(self):
        self.img = st.file_uploader("画像アップロード", accept_multiple_files=True)
    
    def view_ocr(self):
        # 画像がアップロードされていない場合
        if self.img == [] or self.img is None:
            st.write("画像をアップロードしてください")
            return
        
        # OCRの実行
        if st.button("OCR実行"):
            self.ocr_texts = detect_text(self.img[0].read())
        
        if self.ocr_texts is None:
            return
        
        # OCR結果をデータフレームに変換して表示
        self.df_ocr = pd.DataFrame(self.ocr_texts.split("\n"))
        st.dataframe(self.df_ocr, hide_index=True)
        
    def record_result(self):
        # レース結果を記録する場合
        if self.ocr_texts is None:
            return
            
        self.df_log = self.df_ocr.copy()

        self.df_log.insert(0, "1着", False)
        self.df_log.insert(1, "2着", False)
        self.df_log.insert(2, "3着", False)
        self.df_log.columns = ["1着", "2着", "3着", "horse_name"]
        
        self.edit_df = st.data_editor(self.df_log, hide_index=True)
        
        if st.button("レース結果を記録する"):
            update_data(self.edit_df, self.race_name)

メイン部分

Streamlitをつかって表示させた部分。
今回はとりあえずクラスメソッドの中で表示の条件を指定しているが、ここで指定するのもよいと思う。

if "client" not in st.session_state:
    st.session_state.client = RaceData()
    client = st.session_state.client
else:
    client = st.session_state.client
client.select_race()
client.upload_img()
client.view_ocr()
client.record_result()

完成

起動するとこんな感じ。

image.png

レースを選択し、馬の一覧部分のみになっているスクショを撮影→アップロード

そしてレース後に着順を設定して、レース結果を記録したらOK

Undoなどは作ってないので、使う際はGitとかでバージョン管理した方がデータ壊れないかもです....

1
0
0

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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?