Help us understand the problem. What is going on with this article?

Python × Bradley-Terry's Modelでセ・パ両リーグの戦力値遷移を可視化

More than 3 years have passed since last update.

Bradley-Terry's Model

これは、「強さ」を図るモデルです。
簡単にいうと、試合の結果から各々の「強さ」を数値化できるよっていう概念です。
以下の論文が参考になりましたので、詳しくはこちらをご覧ください。
「強さ」に対する定量的評価法とその応用

n個の要素 (チームや個人) があり、何らかの対戦を行うものとする。
対戦は 1要素 対 1要素 のマッチで行われ、その結果は片方の要素の対して勝利、または敗北しか生じないとする。
何回か対戦した結果から各要素の「強さ」をはかるとする。
ここで要素 i が要素 j に勝利する確率を Pij としたとき、すべての組み合わせに対して、
Pij = πi / πi + πj (1)
となるπi を導入する。
式 (1) の関係式を Bradley-Terry(BT)モデルという。
BT モデルにおいて πi は,要素 i の強さを表すと考えることができる。

参考にしたもの

先日参加した、統計処理及び機械学習に基づくデータマイニング勉強会 #03での講義内容を参考にしています。
ここでBradley-Terry's ModelをPythonで実装したものが紹介されています。
(wsに代入されている数字は、交流戦の成績を除いた2014年度のセ・リーグ6球団の総勝数のリストです。便宜上、引き分けを0.5でカウントしています。)
ここで得られたthetaが各チームの「強さ」の数値です。

import numpy as np
theta = np.ones(6)/6.0 # \theta 初期値
t = np.zeros(6)
r = 24.0 # 対戦数
ws = np.array([66.5, 66.5, 66, 56.5, 55, 50.5])  # 総勝数
for iloop in range(0, 100):
    for i in range(0,6):
        acc = 0 # 総和用のアキュムレータ
        for j in range(0,6):
            if (j == i):
                pass
            else:
                acc += r / (theta[i]+theta[j])
        t[i] = ws[i]/acc
    s = sum(t)
    for i in range(0, 6):
        theta[i] = t[i] / s

過去5年間の戦力値遷移

上記のBradley-Terry's Modelを参考に、セ・リーグの5年間の移り変わりをmatplotlibでグラフ化してみました。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import numpy as np
import matplotlib.pyplot as plt
import os

theta = np.ones(6) / 6.0
t = np.zeros(6)
r = 24.0

teams = [u"巨人", u"阪神", u"広島", u"中日", u"横浜", u"ヤクルト"]
colors = ["#f27b00", "#ffff00", "#ff0000", "#002468", "#044a90", "#111c3c"]
scores = [[67.5, 68, 48, 68.5, 42.5, 65.5], [66, 61, 57, 66, 43.5, 66.5], [76.5, 51.5, 55.5, 69, 43, 64.5], [74, 62.5, 58.5, 57.5, 55, 51.5], [66.5, 66.5, 66, 56.5, 55, 50.5]]
years = ["2010", "2011", "2012", "2013", "2014"]
points = [[], [], [], [], [], []]


def reset():
    global theta
    theta = np.ones(6) / 6.0

def bradley_terry(ws):
    for iloop in range(0, 100):
        for i in range(0, 6):
            acc = 0
            for j in range(0, 6):
                if i == j:
                    pass
                else:
                    acc += r / (theta[i] + theta[j])
            t[i] = ws[i] / acc
        s = sum(t)
        for i in range(0, 6):
            theta[i] = t[i] / s

if __name__ == '__main__':
    for score in scores:
        reset()
        bradley_terry(score)
        for i in range(0, 6):
            points[i].append(theta[i])

    for i in range(0, 6):
        data = np.loadtxt(points[i])
        plt.plot(
            data,
            linestyle="-",
            color=colors[i],
            label=teams[i],
            linewidth=2
        )

    plt.ylim(0, 0.5)
    X = np.arange(len(years))
    plt.xticks(X, years)
    plt.tick_params(labelleft="off")
    plt.xlabel("Year")
    plt.ylabel("BradleyTerry Rate")
    plt.title("Central League")
    plt.grid(True)
    plt.legend(loc="best")
    plt.rcParams.update({"font.size": 20})
    os.chdir("graph/")
    plt.savefig("central.eps")

    plt.show()

central.png

こんな感じになりました。
・巨人の安定的な強さ
・中日、ヤクルトの右肩下がり
・広島、横浜の右肩上がり
などが読み取れるのではないでしょうか…

パ・リーグでも同様にやってみると、以下のようなグラフとなります。

pacific.png

セ・リーグのグラフと比較すると6本の折れ線がごちゃごちゃしてるのが特徴的です。
2013年と2014年でABクラスがまるっと入れ替わるということが起きちゃう「混パ」をよく表現できてますね!

massa142
Programming / Perfume / Lacrosse
http://massa142.github.io/
squeeze-inc
「価値の詰まった社会を創る」をビジョンに掲げ、民泊・宿泊チャネルの全物件情報・予約情報・顧客情報を一元管理できる『suitebook』を運営しています。
https://squeeze-inc.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした