見出し画像

単純な集計🐍Pythonで機械学習やろうよ!【第5回】

Pythonでバカが出たぞ!

それ私です。
この😈地獄をあなたに無料でスキルシェア♬

お世話になっております。
合同会社ムジンケイカクプロ 代表ムジンです。

私が独学で困ったことがいっぱい詰まっています。

Excelで集計するのが遅いから、Pythonで代替したいのに、小難しいことばかり書いているページが多いと言われるし、確かにそう思うので、私が実際によくやっている集計を公開する回

Pythonの理解を深めたいんじゃなくて、目前の集計をとっととしたい人向けでしょうね、この記事。

因みに20万行×81列で計算しています。
これで一瞬で計算できる。

口語式簡易設計図

ここで条件を整理1着が何個あるか
その1着が人気◎で勝っているか否か。
それを出すことで、レース場ごとの予想印の正確性に差が出るかわかるやろ。

コード1 準備

import pandas as pd
pd.set_option('display.max_columns', 200)

200行もあれば大丈夫でしょう。
※気になったら検索だ!

コード2 value_counts()

result = df['レース場'].value_counts()
print(result)

レース場という列名を見て、その内容を数える。

コード2の結果

kokura          9798
beppu           6136
nara            5747
matsudo         5571
kochi           5520
aomori          5472
tamano          5446
hakodate        5405
kawasaki        5256
yahiko          5040
toride          4787
ogaki           4767
maebashi        4755
hiratsuka       4555
sasebo          4511
kurume          4398
matsuyama       4387
utsunomiya      4374
takeo           4364
toyama          4354
ito             4346
matsusaka       4331
iwakitaira      4266
toyohashi       4140
keiokaku        4077
hiroshima       4025
omiya           4014
yokkaichi       3904
hofu            3900
mukomachi       3879
seibuen         3726
kishiwada       3690
odawara         3678
fukui           3598
tachikawa       3588
nagoya          3474
shizuoka        3267
gifu            3258
wakayama        3117
takamatsu       3014
komatsushima    2970
Name: レース場, dtype: int64

コード3 query

result = df.query("レース場=='tachikawa'")
print(result.shape)

立川というレース場のレコード(データですね)が、なんぼあるか。

コード4 query 複数条件

df = df.rename(columns={'着順1': 'result'})

着順1という列名をresultに変換(弊社の処理上の問題)

result = df.query("レース場=='tachikawa' and result <= 1")
print(result.shape)

立川レース上の着順が1の数が出た。 
3588レコードある。

result = df.query("レース場=='tachikawa' and result <= 1 and 予 == '◎'")
print(result.shape)

立川レース上の着順が1で予想印が◎の数。
167レコードある。

その確率

result_all = df.query("レース場=='tachikawa'")
print(result_all.shape[0])

result_1 = df.query("レース場=='tachikawa' and result <= 1 and 予 == '◎'")
print(result_1.shape[0])

集計 = result_1.shape[0] / result_all.shape[0]

​print(集計*100)
4.654403567447045

再集計

result_all = df.query("レース場=='hiratsuka'")
print(result_all.shape[0])

result_1 = df.query("レース場=='hiratsuka' and result == 1 and 予 == '◎'")
print(result_1.shape[0])

集計 = result_1.shape[0] / result_all.shape[0]
print(集計*100)
4555
224
4.9176728869374315

特定の列の値を全て変数に格納

df_unique = df.レース場.unique()
print(df_unique)
['hiratsuka' 'iwakitaira' 'matsudo' 'utsunomiya' 'nara' 'sasebo' 'tamano'
'kokura' 'yokkaichi' 'kishiwada' 'beppu' 'gifu' 'hiroshima' 'omiya'
'kawasaki' 'keiokaku' 'matsuyama' 'mukomachi' 'shizuoka' 'toyohashi'
'ito' 'maebashi' 'nagoya' 'takamatsu' 'matsusaka' 'hofu' 'takeo'
'odawara' 'toride' 'kochi' 'ogaki' 'seibuen' 'fukui' 'kurume' 'tachikawa'
'aomori' 'hakodate' 'wakayama' 'yahiko' 'komatsushima' 'toyama']

全てのレース場の確率を出すための準備:ループ

for レース場 in df_unique:
   print(レース場)
hiratsuka
iwakitaira
matsudo
utsunomiya
nara
sasebo
tamano
kokura
yokkaichi
kishiwada
beppu
gifu
hiroshima
omiya
kawasaki
keiokaku
matsuyama
mukomachi
shizuoka
toyohashi
ito
maebashi
nagoya
takamatsu
matsusaka
hofu
takeo
odawara
toride
kochi
ogaki
seibuen
fukui
kurume
tachikawa
aomori
hakodate
wakayama
yahiko
komatsushima
toyama

ちょっと改変して、ループで平均を出していく

for df_racestage in df_unique:
   print("-------------------")
   print(df_racestage)
   result_all = df.query("レース場==@df_racestage")
   print(result_all.shape[0])
   result_1 = df.query("レース場==@df_racestage and result == 1 and 予 == '◎'")
   print(result_1.shape[0])
   print("集計-------------------")
   集計 = result_1.shape[0] / result_all.shape[0]
   print(集計*100)
   print("-------------------")

Queryの中で変数を使う場合は、@が楽。

口語式簡易設計図:ここで条件を整理

競輪予想で使うデータであるので、それを例にご説明。

1着が何個あるか
その1着が人気◎で勝っているか否か。
それを出すことで、レース場ごとの予想印の正確性に差が出るかわかるやろ。

再度調整

for df_racestage in df_unique:
   print("-------------------")
   print(df_racestage)
   result_all = df.query("レース場==@df_racestage and result == 1")
   print(result_all.shape[0])
   result_1 = df.query("レース場==@df_racestage and result == 1 and 予 == '◎'")
   print(result_1.shape[0])
   print("集計-------------------")
   集計 = result_1.shape[0] / result_all.shape[0]
   print(集計*100)
   print("-------------------")

1着の数を出す

result_all = df.query("レース場==@df_racestage and result == 1")

これでまともな確率になったはず。

グラフで可視化するためにリスト化後、データフレームへ変換

ave_list = []

for i, df_racestage in enumerate(df_unique):

   result_all = df.query("レース場==@df_racestage and result == 1")
   result_1 = df.query("レース場==@df_racestage and result == 1 and 予 == '◎'")
   
   ave = result_1.shape[0] / result_all.shape[0]
   ave_list.extend([[df_racestage,ave]])
   
print(ave_list)

df = pd.DataFrame(ave_list)
df.columns = ['place', 'average']
print(df)

ave_list.extend([[df_racestage,ave]])を二重にするのを忘れると、2次元配列にならない。
※うふふ、忘れていたの💔

実際の可視化の前に日本語を表示できるようにする化

import matplotlib.pyplot as plt
import seaborn as sns
from matplotlib.font_manager import FontProperties

font_path = '/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc'
font_prop = FontProperties(fname=font_path)
plt.rcParams['font.family'] = font_prop.get_name()

よくあるやり方?のはず。

可視化

plt.figure(figsize=(20, 10))
plt.title('レース場ごとの予想印が本命で1着だった数の平均')
plt.xticks(rotation=60)
sns.barplot(x='place',y='average', data=df)

並び替え

df_sort = df.sort_values('average', ascending=False)
print(df_sort)

それを描画

plt.figure(figsize=(20, 10))
plt.title('レース場ごとの予想印が本命で1着だった数の平均')
plt.xticks(rotation=60)
sns.barplot(x='place',y='average', data=df_sort)

画像2

ただ、母数が違うからこれではダメだろう

頭を冷やそう。

いや、単純に標準偏差で偏差値を作ろう。
これだ。
予想印毎の着順を、テストの点数に見立てて、合計が少ない方が良い。
偏差値が低いほうが優秀。

ここからは競輪予想のカテゴリに入るので、一旦ここまで。

画像の説明

画像1

単純に平均しただけだと、こんな感じになるが、これだと、レース場毎のレース数が少ないところが有利になってしまう。

レース数が多いが、◎予想で1着が多いところ。
レース数が少ないが、◎予想で1着が多いところ。

これが同等だということになってしまう。
(はず。)

別記事で更に研究しています。

いつもお読みいただき、ありがとうございます。 書くだけでなく読みたいので、コメント欄で記事名入れてもらうと見に行きます。