야구) 피타고리안 승률을 알아봅시다!

3 분 소요

질때는 화끈하게! 이길때는 아슬아슬하게!

  • 그런 팀이 있습니다. 질때는 정말 화끈하게 지는데, 이길때는 늘 아슬아슬하게 이깁니다. 2016, 2017년의 한화가 사실 늘 이런 모습을 보여줬죠. 그래서 초반에는 아슬아슬하게 이겨서 어느 정도의 순위를 유지하다가도 경기 후반으로 가면 당연히 순위가 아래로 쭉 떨어져 있는 것을 알수 있습니다. 경기가 반복되면 일시적인 현상들은 대부분 없어지고, 수렴하게 되니까요.
  • 피타고리안 레코드는 ‘결국 팀의 총 득점과 총 실점 만으로 팀의 기대승률을 계산하는 방법’을 말합니다. 공식이 삼각형 빗변을 구하는 공식과 비슷해서, 피타고리안 레코드라고 합니다.

기대승률 그리고 변종

  • 다음의 방식으로 간단하게 계산합니다. X에는 2가 보통 오는데, 기존 시즌 데이터를 활용해서 회귀분석을 해본 결과 1.82가 적합하다는 의견도 있죠.
\[Exp. Win% = RS(Run Scored)^X / (RS^X+RA(Run ALlowed)^X)\]
  • 또 그래서 정확한 X는 다음의 방식으로 구하는 경우도 있습니다. 물론 복잡해지기 때문에, 저는 그냥 1.87을 곱하기로 합니다.
\[X = ((RS+RA) / G)^(0.287)\]

이게 왜 되죠? (논문에서 된데요)

  • 처음에는 피타고리안 승률이 존나 말도 안된다고 생각했는데, 이를 증명하는 2006년에 나온 논문이 있습니다.
  • 이 논문에서 증명하려고 한 것은, 우선 RS(Runs Scored)와 RA(Runs Allowed)가 통계적으로 독립적이다 라는 것을 증명하고, 각각이 특정 분포를 따르는 상황에서 가장 잘 추정할 수 있는 X를 찾는 것입니다.
    • RS, RA를 각각 weibull dist를 따른다고 하고 진행하였고, X 값이 1.82보다는 1.79(lease square), 1.74(maximum likelihood)가 적합하다고 얘기하기도 합니다.
  • 논문을 더 보면 이해할 수 있을 것 같긴 한데(정말이에요! 저 나름 공대 대학원생입니다), 시간이 좀 걸릴 것 같아서 일단 보지 않겠습니다 하하핫.

2018년 5월 23일, 현재까지의 KBO에 적용해봅시다.

  • 아무튼, 그래서 오늘의 KBO에 이를 한번 적용해보겠습니다. 스태티즈에서 자료를 긁어왔습니다.

  • 결과를 보면…원래 2위이던 한화가 7등으로 떨어지는 것을 알 수 있습니다. 더이상 말하지 않겠습니다 제기랄.
    • 다만, 그러함에도 약간 흥미로운 것은 한화는 득점도 적지만, 실점도 다른 팀과 비교해보면 가장 낮은 것을 알 수 있습니다.
    • 음, 그래도 기아/스크/두산 의 경우는 득점이 실점에 비해서 월등히 높은데, 한화는 너무 초라하군요.
  • 슬램덩크의 강백호처럼 “약한 사람에게는 약하고, 강한 사람에게는 강한 모습”을 보여주는 것이 아닐까, 생각을 해봅니다만….변명이겠죠.
      RA     RS     g   l name   w         X        py
3  230.0  270.0  46.0  22  KIA  24  3.119565  0.622506
2  230.0  264.0  46.0  20   SK  26  3.082130  0.604663
0  239.0  271.0  46.0  16   두산  30  3.181957  0.598647
4  231.0  246.0  49.0  25   LG  24  2.793857  0.543830
6  231.0  235.0  45.0  23   롯데  22  2.972044  0.512753
5  242.0  245.0  49.0  25   넥센  24  2.852428  0.508785
1  224.0  222.0  46.0  19   한화  27  2.782652  0.493761
7  263.0  239.0  47.0  27   kt  20  3.065404  0.427189
8  270.0  236.0  48.0  28   삼성  20  3.025458  0.399584
9  265.0  197.0  48.0  30   NC  18  2.762375  0.305951
input_s = """1	두산	46	30	16	0	-	0.652	271	239
2	한화	46	27	19	0	3.0	0.587	222	224
3	SK	46	26	20	0	4.0	0.565	264	230
4	KIA	46	24	22	0	6.0	0.522	270	230
5	LG	49	24	25	0	7.5	0.490	246	231
5	넥센	49	24	25	0	7.5	0.490	245	242
7	롯데	45	22	23	0	7.5	0.489	235	231
8	kt	47	20	27	0	10.5	0.426	239	263
9	삼성	48	20	28	0	11.0	0.417	236	270
10	NC	48	18	30	0	13.0	0.375	197	265"""

import pandas as pd
df = {
    'name':[],
    'g':[],
    'w':[],
    'l':[],
    'RS':[],
    'RA':[]
}
for s in input_s.split("\n"):
    try:
        _, name, g, w, l, _, _, _, RS, RA = s.split("\t")
        df['name'].append(name)
        df['g'].append(g)
        df['w'].append(w)
        df['l'].append(l)
        df['RS'].append(RS)
        df['RA'].append(RA)
    except:
        print(len(s.split("\t")))
        print(s.split("\t"))
df = pd.DataFrame(df)
df['RS'] = df['RS'].astype('float32')
df['RA'] = df['RA'].astype('float32')
df['g'] = df['g'].astype('float32')
df['X'] = (df['RS'] + df['RA'])/df['g'] * 0.287
df['py'] = [df.iloc()[i]['RS']**X / (df.iloc()[i]['RS']**X + df.iloc()[i]['RA']**X) for i, X in enumerate(df['X'])]

#df['pyW'] = df['py']*df['g']
print(df.sort_values('py', ascending=False))

wrap-up

  • 아무튼, 간단하게 피타고리안 승률을 정리해봤습니다만, 유쾌하지 않군요. 한화는 지금의 순위가 운인것 같습니다. 그저 떨어지지 않기를 기도합니다.
  • 단, 한화의 경우 다른 팀들에 비해서 총 실점이 매우 낮은 편인 것을 알 수 있습니다. 이 지점이 어느 정도 변수가 될 수 있지 않을까 싶었는데, 어제는 두산으로부터 쳐맞았기 때문에 별 차이가 없겠네요. 후.

reference

댓글남기기