bskyvision RSS 태그 관리 글쓰기 방명록
2021-03-03 15:01:54
728x90

야구는 기본적으로 상대방보다 더 많은 득점을 기록하는 팀이 이깁니다. 따라서, 한 시즌의 득점과 실점의 비율과 승률 사이에는 강한 상관관계가 있습니다. 아래 산점도(scatter plot)는 MLB의 1954년부터 2019년까지의 팀 득실점 비율과 승률 사이의 상관관계를 보여줍니다. 여기서 각 포인트는 어떤 해, 어떤 팀의 득실점 비율과 최종 승률을 보여줍니다.  

 

 

피어슨 상관계수를 구했더니 무려 0.9319입니다. 즉, 시즌 총득점과 총실점의 비율과 승률 사이에는 매우 강한 상관관계가 있다는 것입니다. 

 

이 관계를 잘 모델링해낼 수 있는 식을 빌 제임스라는 사람이 만들었습니다. 바로 피타고리언 승률(Pythagorean expectation)이라고 불리는 다음 식입니다. 

 

 

총득점은 영어로 보통 RS로, 총실점은 RA로 줄여서 표기합니다. 이 식의 그래프를 위 산점도와 함께 그리면 다음과 같습니다. 

 

 

보시다시피 저 관계를 이 식이 잘 설명해내죠? 지수를 2로 했는데, 1.83으로 하면 좀 더 정확하다고 합니다. 그래서 미국의 유명 야구 통계 사이트인 베이스볼 레퍼런스는 2가 아닌 1.83을 사용한다고 합니다.  

 

 

지수를 1.83으로 해준 다음, 다시 그래프를 그려보겠습니다. 

 

 

육안으로 봤을 때는 큰 차이는 없어보입니다만, 1.83이 좀 더 정확하게 둘 사이의 관계를 모델링 해낸다고 합니다. 

 

피타고리언 승률을 어떻게 활용하는 것이 좋을까?

이 피타고리언 승률을 어떻게 활용할 수 있을까요? 어떤 팀이 시즌 절반을 마친 상황에서 승률이 6할이었다고 가정해보겠습니다. 그런데, 피타고리언 승률을 구해봤더니 5할이었다면, 이 팀은 현재까지 운이 좋은 편이었다고 볼 수 있습니다. 피타고리언 승률이 5할이라는 뜻은 총득점수와 총실점수가 완전히 같았다는 것입니다. 1/(1 + 1) = 0.5

 

그런 상황에서 6할의 승률을 거둔 것이니 비교적 운이 좋았다고 볼 수 있는 것이죠. 하지만, 남은 경기들에서도 지금과 같이 1에 가까운 득실점 비율을 기록한다면, 남은 경기에서는 5할 근처의 승률을 거둘 가능성이 큽니다. 지금처럼 운이 계속 좋지 않은 이상 말이죠. 

 

이미 치룬 절반의 시즌에서는 6할의 승률을 기록했고, 남은 절반 시즌의 기대 승률은 5할이므로 55% 정도의 승률로 시즌을 마무리할 가능성이 있습니다. 실제 사례를 살펴보면 이 예측에서 크게 벗어나지 않는다고 합니다. 

 

따라서, 실제 승률이 피타고리언 승률보다 높은 팀들은 "지금까지 운이 좋았구나"라고 겸손히 현재의 결과를 받아들인 후, 남은 시즌 득점을 높이고 실점을 줄일 방안을 모색하는 것이 좋습니다. 반대로 실제 승률이 피타고리언 승률보다 낮은 팀들은 현재 결과에 너무 낙심하지 말고, 잘하고 있다는 자신감을 갖고 시즌을 끝까지 이어갈 필요가 있을 것입니다. 

 

소스코드

오늘 이 포스팅의 자료는 다음과 같은 파이썬 코드로 만들었습니다. 필요하신 분은 참고하시기 바랍니다. 참고로 데이터를 얻기 위해 저는 레먼 데이터베이스(sqlite 버전)를 활용했습니다. 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import sqlite3
import numpy as np
from scipy import stats
import matplotlib.pyplot as plt
 
with sqlite3.connect("lahmansbaseballdb.sqlite"as con:
    cur = con.cursor()
    cur.execute('''select W, L, R, RA from teams where yearID >= 1954;''')
    W_L_RS_RA = cur.fetchall()
 
    W = np.zeros((len(W_L_RS_RA)))
    L = np.zeros((len(W_L_RS_RA)))
    RS = np.zeros((len(W_L_RS_RA)))
    RA = np.zeros((len(W_L_RS_RA)))
 
    for i in range(len(W_L_RS_RA)):
        W[i] = W_L_RS_RA[i][0]
        L[i] = W_L_RS_RA[i][1]
        RS[i] = W_L_RS_RA[i][2]
        RA[i] = W_L_RS_RA[i][3]
 
    WPCT = W/(W+L)
    RS_RA_ratio = RS/RA
 
    x = np.arange(0.51.60.001)
    Pythagorean_expectation2 = 1 / (1 + (1 / x) ** 2)
    Pythagorean_expectation183 = 1 / (1 + (1 / x) ** 1.83)
 
    plt.scatter(RS_RA_ratio, WPCT, c='b')
    plt.plot(x, Pythagorean_expectation2, 'r', label='2.0')
    plt.plot(x, Pythagorean_expectation183, 'r--', label='1.83')
    plt.title('Correlation between RS_RA_ratio and WPCT')
    plt.xlabel('RS_RA_ratio')
    plt.ylabel('WPCT')
    plt.grid(True)
    plt.legend()
    plt.show()
 
    print("Pearson correlation coefficient:", stats.pearsonr(RS_RA_ratio, WPCT)[0])
cs

 

 

bskyvision의 추천글

[세이버메트릭스] 레먼 데이터베이스에서 류현진 선수 MLB 기록 살펴보기(sqlite3)

[세이버메트릭스] 타율이 높은 팀 vs OPS가 높은 팀, 누가 이길까?

 

참고자료

[1] 벤저민 바우머, 앤드루 짐발리스트 지음, "세이버메트릭스 레볼루션"

[2] namu.wiki/w/%ED%94%BC%ED%83%80%EA%B3%A0%EB%A6%AC%EC%95%88%20%EC%8A%B9%EB%A5%A0, 나무위키, "피타고리안 승률"

 

댓글

방문해주신 모든 분들을 환영합니다.

* 글을 읽던 중에 궁금했던 부분은 질문해주세요.

* 칭찬, 지적, 의문, 격려, 감사표현 등을 남겨주세요.

* 최대한 답변 드리도록 노력하겠습니다.

* 욕설과 광고를 담은 댓글은 가차없이 삭제합니다.


  1. BlogIcon 푸쿵@2021.03.03 16:15 신고 ~$ 개인적으로 야구도좋아하고 분석도 해봤는데 수학적으로 다가가니까 새롭네요^^ [댓글주소]  [수정/삭제]  [답글작성]
    • BlogIcon bskyvision@2021.03.03 16:34 신고 ~$ [답글]: 푸쿵님 안녕하세요.ㅎㅎ 저도 지금까지는 그저 재밌게 경기를 시청해왔는데, 이렇게 수학적으로 간단하게라도 분석해보니 좀 더 재밌는 것 같습니다. ㅎㅎ [댓글주소]  [수정/삭제]
guest@이름 ~$
guest@패스워드 ~$
guest@홈페이지주소작성 ~$

guest@댓글작성 ~$




bskyvision. Designed by bskyvision.