2025 MLB · Home & Away · 2,425 Games

김민주

Sports Data Analyst — In Training

한 시즌을 홈과 원정으로 갈라 보면서 평균 하나로 답하지 않는 법을 배우고 있습니다.

리그 평균 홈 어드밴티지 · 2025 정규시즌
+8.7 %p

30개 구단을 하나씩 세어 보면

−4.9 ~ +21.0 %p

리그 홈 승률 54.3%는 사실입니다. 하지만 이 한 줄로 30개 구단을 설명하면 홈에서 21.0%p 더 강한 파이리츠와, 홈에서 오히려 4.9%p 약한 애슬레틱스가 같은 팀이 됩니다. 홈 이점이 마이너스인 구단이 셋 있었습니다. 이 포트폴리오는 그 평균을 30조각으로 쪼개 본 기록입니다.

2,425
정규시즌 경기
4,858
팀-경기 행
30
구단 홈·원정 분할
4
분석 프로젝트

Focus

관심 분야

“홈에서 더 잘한다”는 야구에서 가장 오래된 통념입니다. 그런데 얼마나, 어느 팀이, 왜 더 잘하는지는 거의 이야기되지 않습니다. 이 세 가지 질문을 축으로 공부하고 있습니다.

How much

홈 이점의 크기를 재는 일

리그 평균은 8.7%p지만 그 안에는 21%p부터 마이너스까지가 섞여 있습니다. 하나의 평균을 팀 단위로 쪼갤 때 비로소 쓸모 있는 숫자가 된다고 생각합니다.

Who

원정에서 무너지는 팀 찾기

순위표는 홈과 원정을 합친 결과만 보여 줍니다. 둘을 나누면 같은 승률을 가진 두 팀이 전혀 다른 팀이라는 게 드러납니다. 포스트시즌 예측에서 특히 중요한 구분입니다.

Why

이점의 출처를 분해하기

홈에서 더 이기는 이유가 타선이 살아나서인지, 마운드가 덜 맞아서인지, 구장 자체 때문인지를 나눠 봅니다. 데이터가 어디까지 답할 수 있고 어디서 멈춰야 하는지를 함께 밝히는 연습이기도 합니다.

Selected Work · Home & Away, 2025 MLB

프로젝트

Baseball Savant · MLB Stats API 기반 2025 시즌 경기 데이터를 Python으로 정리했습니다. 시범경기·올스타전·일본 구단·마이너리그 팀을 걷어내고 남은 정규시즌 2,425경기(팀 시점 4,858행)가 분석 대상입니다. 아래 수치는 모두 원본에서 직접 계산했습니다.

구단 로키스COL 아래 세 프로젝트가 모두 이 구단 기준으로 바뀝니다 · 홈 81경기 / 원정 81경기

MLB 30개 구단

01

Question 1

우리 팀은 홈에서 얼마나 강한가

30개 구단의 홈 승률과 원정 승률을 각각 구하고, 홈구장이 얼마나 타자 친화적인 곳인지를 붙였습니다. 리그 전체로는 홈 21팀이 5할 이상이지만, 팀마다 사정이 전혀 다릅니다. 위 필터에서 구단을 바꿔 보세요.

선택 구단 — 로키스

홈구장
홈구장 한 경기 양팀 합계 득점 · 리그 평균 8.90점
홈 승률
원정 승률
전체 승률

세로선은 승률 5할 · 괄호 안은 리그 순위

리그 전체 홈 승률은 54.3%입니다. 홈에서 5할을 넘긴 팀은 21개인데, 원정에서 5할을 넘긴 팀은 10개뿐이었습니다. 홈 승률만 보면 리그의 3분의 2가 강팀처럼 보인다는 뜻이라, 홈 성적만으로 팀을 평가하면 거의 항상 과대평가하게 됩니다.

02

Question 2

원정에서 우리 팀은 얼마나 버티는가

같은 데이터를 원정 쪽에서 다시 봤습니다. 30개 구단을 홈 승률 − 원정 승률 순으로 세우면 리그 평균 8.7%p 안에 숨어 있던 편차가 드러납니다. 오른쪽으로 길수록 집에서만 강한 팀입니다.

홈 승률 − 원정 승률 · 30개 구단 홈이 강함원정이 강함
21
홈 5할 이상 구단
10
원정 5할 이상 구단
3
홈 이점 마이너스 구단

원정 승률 최하위는 로키스의 .222였습니다. 홈에서는 .309를 기록했으니 쿠어스필드를 벗어나면 완전히 다른 팀이 됩니다. 반대로 애슬레틱스·말린스·내셔널스 셋은 원정에서 더 잘했습니다. “홈 이점은 모든 팀에 똑같이 주어진다”는 전제가 성립하지 않는다는 뜻이고, 홈 이점을 일괄 보정하는 예측 모델이 이 세 팀에서 계속 틀리는 이유이기도 합니다.

같은 득점, 다른 승률 — 홈 vs 원정 원정
승률 5할

우리 팀 득점 (점)

중계에서 자주 듣는 “3점은 내야 해볼 만하다”를 홈·원정으로 갈라 확인했습니다. 승률이 5할을 넘어서는 지점이 홈에서는 4점, 원정에서는 5점이었습니다. 같은 4점을 뽑아도 홈에서는 57.1%로 이기는 점수지만 원정에서는 47.2%로 지는 점수입니다. 원정 경기에서 감독이 한 점을 더 짜내려고 번트를 대는 장면에는 근거가 있는 셈입니다.

7점 이상 구간에서 원정이 더 높게 나오지만 각 150~200경기 수준의 표본이라 뒤집힘으로 읽지 않았습니다.

03

Question 3

홈에 오면 달라지는 건 타선인가, 마운드인가

홈 이점이 어디서 오는지 보려고 딱 두 가지만 비교했습니다. 홈에서 몇 점을 더 뽑는지, 그리고 홈에서 몇 점을 덜 내주는지. 팀마다 답이 다릅니다. 위 필터의 구단이 그대로 적용됩니다.

선택 구단 — 로키스 · 경기당 평균 점수

타선 — 우리가 낸 점수
경기당 평균 득점
원정
마운드 — 우리가 준 점수
경기당 평균 실점
원정

타선형
12팀
홈에서 방망이가 살아나는 쪽으로 이득을 봅니다.
    마운드형
    11팀
    홈에서 실점을 줄이는 쪽으로 이득을 봅니다.
      이점 없음
      7팀
      홈에서 나아지는 쪽이 없습니다. 오히려 나빠지는 팀도 섞여 있습니다.

        리그 전체로는 타선형 12팀, 마운드형 11팀으로 거의 반반이었습니다. 홈 이점이 한 가지 이유로 생기는 게 아니라는 뜻입니다. 가장 재밌는 팀은 로키스입니다. 홈에서 경기당 1.75점을 더 뽑지만 1.72점을 더 내줍니다. 쿠어스필드는 우리 타선에만 좋은 구장이 아니라 상대 타선에도 똑같이 좋은 구장이라, 리그 최고의 타자 친화 구장을 쓰고도 홈 이점은 평균 수준에 그칩니다.

        선발 예고 등판 경기의 팀 실점 · 홈 vs 원정

        홈·원정 각각 10경기 이상 예고 선발로 나선 투수 109명 중 격차 상하위 5명

        이 분석의 한계 — 먼저 밝힙니다

        선수 단위 홈·원정 성적은 이 데이터로는 정확히 구할 수 없습니다. 타자·투수 파일은 시즌 합계만 담고 있어 홈/원정 구분 컬럼이 없습니다. homeRuns 는 이름과 달리 홈경기가 아니라 홈런이고, 두 파일 어디에도 경기 단위 기록이 없습니다.

        그래서 경기 파일의 my_pitcher(예고 선발)를 이용해 그 투수가 선발 예고된 경기의 팀 실점을 대신 봤습니다. 투수 개인의 자책점이 아니라 불펜과 수비가 섞인 값이고, 홈·원정 각각 13~16경기 수준이라 우연의 폭도 큽니다. 순위표가 아니라 “다음에 확인해 볼 후보 목록”으로 읽어야 하는 숫자입니다.

        제대로 하려면 MLB Stats API의 경기별 박스스코어를 선수 단위로 수집해 player_id 로 결합해야 합니다. 지금 진행 중인 작업입니다.

        04

        Question 4

        터뜨려야 이기나, 막아야 이기나

        03이 “홈에서 뭐가 좋아지나”였다면 이건 “그래서 뭐가 이기게 하나”입니다. 타선이 터진 날과 마운드가 틀어막은 날의 승률을 비교했습니다. 기준은 6점 이상 득점2점 이하 실점인데, 둘 다 시즌의 31%씩 일어나 빈도가 거의 똑같습니다. 자주 일어나는 쪽이 유리해 보이는 착시를 없애려고 이렇게 맞췄습니다.

        그날의 경기력 × 승률 · 리그 전체 4,858 팀-경기
        마운드 O
        2점 이하 실점
        마운드 X
        3점 이상 실점
        타선 O
        6점+ 득점
        100.0%
        469경기 · 전부 승리
        78.0%
        1,049경기 · 타선만 터진 날
        타선 X
        5점 이하 득점
        79.9%
        1,037경기 · 마운드만 막은 날
        13.6%
        2,303경기 · 둘 다 안 된 날

        둘 다 되면 469전 469승 — 6점을 내고 2점만 주면 질 수가 없으니 계산해 볼 것도 없는 칸입니다. 하나만 되는 두 칸(78.0% vs 79.9%)이 이 질문의 진짜 핵심입니다.

        한쪽만 되는 날의 승률은 타선 78.0%, 마운드 79.9%로 사실상 붙어 있습니다. 1.9%p 차이는 각 1,000여 경기 표본에서 우연으로도 충분히 나올 수 있는 크기라, “야구는 투수 놀음”이라는 말을 이 숫자만으로 확인해 주기는 어렵습니다. 정작 눈에 띄는 건 마지막 칸입니다. 6점을 못 내고 3점 이상 내준 날, 그러니까 전체 경기의 절반(47.4%)은 승률이 13.6%까지 떨어집니다. 승부는 잘한 날이 아니라 못한 날에 갈립니다.

        그런데 홈에서는 답이 뒤집힙니다 타선이 터진 날마운드가 막은 날
        홈경기 2,429 팀-경기
        타선이 터짐83.3%
        마운드가 막음89.8%

        홈에서는 막는 쪽이 6.5%p 우위입니다. 2점 이하로 묶으면 열 번 중 아홉 번 이겼습니다.

        원정경기 2,429 팀-경기
        타선이 터짐86.3%
        마운드가 막음82.0%

        원정에서는 터뜨리는 쪽이 4.3%p 우위로 순서가 바뀝니다.

        리그 전체로는 붙어 있던 두 값이 홈·원정을 가르자 +6.5%p와 −4.3%p로 갈라졌습니다. 야구 규칙을 생각하면 자연스럽습니다. 홈팀은 앞서 있으면 9회말을 치지 않고 경기를 끝내므로 “막으면 이긴다”가 더 강하게 성립하고, 원정팀은 몇 점을 내든 마지막 공격 기회가 항상 상대에게 남아 있습니다. 실제로 2점 이하로 막는 일 자체도 홈에서 33.2%, 원정에서 28.8%로 홈이 더 잦았습니다.

        그럼 우리 팀은? — 구단별 승률과 95% 신뢰구간

        선택 구단 — 로키스

        타선이 터진 날
        6점+ 득점
        리그 84.8%
        마운드가 막은 날
        2점− 실점
        리그 86.2%
        0%50%100%

        굵은 막대 = 그 팀의 실제 승률 · 아래 가느다란 구간 = 95% 신뢰구간(참값이 들어 있을 범위) · 세로선 = 리그 평균

        구단별로 나눠 보면 표본이 팀당 20~70경기로 줄고, 신뢰구간은 평균 ±19%p까지 벌어집니다. 그 결과 두 구간이 겹치지 않아 “이 팀은 마운드형”이라고 말할 수 있는 구단은 30개 중 단 하나, 다이아몬드백스뿐이었습니다(타선 72.6% vs 마운드 95.3%). 나머지 29개 구단은 숫자에 차이가 보여도 우연의 폭 안에 들어갑니다. 팀별 순위표를 만들어 “우리 팀은 투수 놀음”이라고 말하고 싶은 유혹이 생기는 지점인데, 한 시즌 데이터로는 거기까지 갈 수 없다는 게 정직한 결론입니다. 여러 시즌을 쌓아야 답할 수 있는 질문입니다.

        임계값 6점·2점은 두 사건의 발생 빈도가 31%로 맞아떨어지는 지점을 찾아 정했습니다. 기준을 5점·3점으로 바꿔도 방향은 같았습니다.

        Audit Log · 계산보다 먼저 한 일

        홈과 원정을 나누기 전에

        경기 데이터를 홈·원정으로 가르는 작업은 필터 한 줄처럼 보이지만, 그 한 줄이 어긋나면 이후 모든 승률이 조용히 틀립니다. 아래는 실제로 확인하고 걸러낸 여덟 가지입니다. 오류 메시지가 뜬 건 하나도 없었습니다.

        파일
        컬럼
        무엇을 확인했나
        어떻게 처리했나
        B4 LONG
        runs_scored / runs_allowed홈 득점 이득
        리그 전체 홈 득점 이득(+0.091)과 홈 실점 이득(+0.091)이 소수점까지 같아서 “교차 검증됐다”고 쓸 뻔했습니다. 같은 경기를 두 시점으로 넣은 표라 리그 합계에서는 구조상 항상 같을 수밖에 없는 값이었습니다.
        리그 단위 분해를 폐기
        팀 단위로만 계산
        B4 LONG
        venue_name경기장
        원정 시점 행에도 실제 경기장(=상대 홈구장)이 그대로 적혀 있습니다. 이 파일에서 구장별로 묶으면 모든 경기가 두 번 세어져 표본 수가 두 배로 부풀어 오릅니다.
        홈구장 추출은 is_home == 1 로 필터
        구장 집계는 B3에서 수행
        B3 WIDE
        is_postseason포스트시즌 여부
        “정규시즌이 아니면 포스트시즌”이라는 규칙 탓에 시범경기 357건과 올스타전까지 1로 잡혀 있었습니다.
        컬럼을 버리고 game_type 사용
        404경기47경기
        B3 WIDE
        game_id경기 고유번호
        “고유번호”라는 이름과 달리 네 경기가 두 번씩 들어 있었습니다. 모든 컬럼 값이 같은 완전 중복이었고, 넷 다 정규시즌 경기였습니다.
        중복 제거
        2,833행2,829행 (정규시즌 2,425)
        B4 LONG
        team우리 팀
        MLB 30개 구단 외에 올스타팀, 한신 타이거스·요미우리 자이언츠, 마이너리그 4개 팀이 섞여 팀 목록이 39개였습니다.
        MLB 30개 구단으로 필터
        39개 팀30개 팀
        B4 · 통과
        is_home홈경기 여부
        홈/원정 분할의 기준이 되는 컬럼이라, 쓰기 전에 평균을 확인했습니다. 정확히 0.5였고 팀별 홈 81경기·원정 81경기로 떨어졌습니다.
        모든 경기가 두 시점으로 빠짐없이 들어감
        그대로 사용
        B2 PITCHING
        winPercentage승률
        승·패가 모두 0인 투수 2명의 값이 .--- 로 적혀 있어 475행짜리 숫자 컬럼 전체가 문자열로 읽혔습니다.
        승÷(승+패)로 직접 계산
        473행 복구, 분모 0은 결측 처리
        B1 · B2
        homeRuns / Position이름이 헷갈리는 컬럼
        homeRuns 는 홈경기 기록이 아니라 홈런입니다. 홈·원정 분석에 쓰려다 이름만 보고 잘못 잡을 뻔했습니다. Position 은 936행 전체가 비어 있습니다.
        선수 단위 홈·원정 분석은 불가로 판정
        프로젝트 03에 한계로 명시

        Toolkit

        쓰는 도구

        이 프로젝트를 하면서 실제로 손에 익힌 것들입니다.

        분석

        • Python · pandas · NumPy
        • Wide ↔ Long 변환과 집계 단위 설계
        • SQL — 조인, 그룹별 집계, 윈도우 함수

        통계

        • 부분집단 분해와 심슨의 역설
        • 표본 크기와 우연의 폭 판단
        • 상관과 인과의 구분, 교란 변수

        시각화

        • Matplotlib · Seaborn
        • Tableau 기초
        • HTML · CSS · SVG 직접 구현

        도메인

        • 홈 어드밴티지 · 파크 팩터
        • 세이버메트릭스 지표 (OPS · wRC+ · FIP)
        • MLB Stats API · Baseball Savant · KBO 기록

        Contact

        평균 뒤에 뭐가
        있는지 같이
        볼 팀을 찾습니다.

        스포츠 구단 데이터팀, 스포츠 마케팅 분석, 스포츠 미디어 데이터 직무의 인턴십과 신입 채용에 관심이 있습니다. 데이터를 주시면 먼저 검산부터 하겠습니다.