PSM

Pプログラミング S初心者の Mメモ書き

Pythonで麻雀の戦績を集計してみた

1 初めに

前回の投稿に引き続き,記録をとっていた最近の戦績を集計してみました.
基本的にはpythonのpandasしか使ってないのですが,集計してみたり,for文回してみたり,DataFrame 結合してみたり,ブロードキャストについて思い出したりと結構よい勉強になりました.
それではいよいよ実際に行った作業に移ります.


2 やったこと

こんな感じのデータを読み込みます.
f:id:muromura:20170510223606p:plain
列が各対局者,行が半荘ごとの成績(得点)となっています.
対局に参加していない人の欄は空白になっており,pythonではNaNとして読み込まれます.

3行目から6行目はエクセルで順位つけようとして途中で面倒になってやめた名残です.
不要行削除の例示に都合良いのでそのままにしておきます.



1行を削除するときには,配列のスライスと同じように指定すれば良いです.

#不要部分削除
hoge[:5]

列を削除するときにはdrop()を使います.

#不要部分削除
data = data.drop("削除したい列名", axis=1)

対局数をカウントするのには,NaNの数を利用することにしました.
各列ごとにis.null()でNaNの数を調べるとTrue/Falseで結果が帰ってきます.
pythonにおいてはTrue/Falseは数値計算すると1/0に等しくなるので,結果を1から引いてやることで各列で対局に参加した部分(=得点が入力されている部分)を1,それ以外を0とすることができました.
あとはそれを合計するだけです.

#対局数
(1-data.isnull()).sum()

順位の集計にはちょっと手間取りました.
rank()を使えば良いのですが,このとき行ごとに順位を出すには,引数でaxis=1を指定します.
ちなみにこのときNaNはNaNのまま無視してくれました.便利!

rank()を使うと数が少ない順に1から数字が振られるので,本来の順位とは逆になってしまいます.
それをひっくり返すためには5から順位を引けば良いことになります.
これはpythonのブロードキャストを使って簡単に書けました.

#順位づけ
rank = data.rank(axis=1)
rank= 5 - rank

次に,1位から4位までそれぞれの順位を何回とったか数えます.
たぶん他にもっと良い方法があると思いますが,思いつかなかったので,各列ごとに抜き出してvalue_counts()で集計し,後でそれを全部くっつけるという方法をとることにしました,
最初に空のDataFrameを用意し,colmuns()でとってきた列名でfor文を回して集計結果をくっつけています.
DataFrameの結合にはconcat()を使い,列方向にくっつけたいときにはaxis=1を指定します.

#各順位を何回とったかの集計
#列名を取得
players = rank.columns
#空のデータフレームを用意
ranks = pd.DataFrame(index=[1,2,3,4], columns=[])
#for文で回してranksに突っ込んでいく.
for player in players:
    r = rank[player].value_counts()
    ranks = pd.concat([ranks, r], axis=1)

3 サンプルコード

というわけで長くなってしまいましたが,サンプルコードは以下.

import numpy as np
import pandas as pd

#データ読み込み
raw_data = pd.read_csv("sample.csv", encoding="sjis")

#不要な部分を切り捨てる
data = pd.DataFrame(raw_data[5:])
data = data.drop("day", axis=1)
#型をチェック
#data.dtypes

#順位づけ
rank = data.rank(axis=1)
rank= 5 - rank

#対局数
(1-data.isnull()).sum()

#平均順位算
rank.mean()

#合計計算
data.sum()

#平均得点計算
data.mean()

#順位合計
players = rank.columns
players
ranks = pd.DataFrame(index=[1,2,3,4], columns=[])
for player in players:
    r = rank[player].value_counts()
    ranks = pd.concat([ranks, r], axis=1)

#集計
result = pd.concat([(1-data.isnull()).sum(),
                    ranks.T,
                    rank.mean(),
                    data.sum(), 
                    data.mean()],
                   axis=1, join='inner').T

result.index=['対局数',"1位","2位","3位","4位",'平均順位','合計得点','平均得点']
result = result.round(2)

結果はこんな感じになります.
f:id:muromura:20170510224213p:plain


また時間のあるときに,次は各日ごとの集計をしたり,player同士の相性を計算したりなどやっていきたいと思います.
適当ですが,得点の相関係数とかでも相性の指標になりうるかもしれませんね.