야구 분석/Python

히트 스프레이 차트에 야구장 사진 넣어보기

sam_j_s 2024. 5. 22. 23:21
728x90
반응형

시각화 주제

 

히트 스프레이 차트 만들어보기

시각화 주제KBO나 MLB의 선수 기록을 확인하는 사이트인 스탯티즈나 베이스볼 서번트에서 타자의 기록을 확인할 때마다 나오는 히트 스프레이 차트가 있습니다. 타자의 안타, 2루타, 3루타, 홈런

bbdiary03.tistory.com

 
저번에 만들어 놓은 히트 스프레이 차트의 배경에 야구장 이미지를 넣어보겠습니다.
 

데이터 출처

메이저리그 데이터를 분석하기 위해 개발된 오픈 소스 라이브러리인 pybaseball을 사용했습니다. 이 라이브러리는 주로 여러 공개 데이터 소스에서 정보를 수집하며, 이 데이터는 Retrosheet, Baseball Savant, Fangraphs 등과 같은 웹사이트에서 제공됩니다.
 

시각화

패키지 임포트

import base64
from pathlib import Path
import plotly.graph_objects as go
import pybaseball
import pandas as pd

 

배경 사진 넣기

우선 만들어 놓은 야구장 사진을 넣어주겠습니다.
 
Plotly에서는 로컬 이미지 파일을 배경으로 설정하려면 이미지를 Base64 인코딩 문자열로 변환한 뒤 데이터 URL로 사용하는 방법을 적용해서 넣어주어야 합니다.
 

# 이미지 파일을 Base64로 인코딩하는 함수
def encode_image(image_path):
    with open(image_path, "rb") as image_file:
        return base64.b64encode(image_file.read()).decode('ascii')

# 이미지 파일 경로
image_path = '이미지'  # 로컬 이미지 파일 경로 지정

# Base64 인코딩
encoded_image = encode_image(image_path)

# 특정 선수의 2023년 시즌 타구 데이터 가져오기
data = pybaseball.statcast_batter('2023-01-01', '2023-12-31', player_id='571448')

# 필요한 데이터 필터링
hits_data = data[data['events'].isin(['single', 'double', 'triple', 'home_run'])]

# 그래프 객체 생성
fig = go.Figure()

# 타구 결과별로 데이터 추가
for hit_type, color in zip(['single', 'double', 'triple', 'home_run'], ['blue', 'orange', 'green', 'red']):
    subset = hits_data[hits_data['events'] == hit_type]
    fig.add_trace(go.Scatter(
        x=subset['hc_x'], y=subset['hc_y'], mode='markers', 
        marker=dict(size=12, color=color, line=dict(width=2, color='black')), 
        name=hit_type
    ))

# 배경 이미지 설정
fig.update_layout(
    images=[dict(
        source='data:image/png;base64,{}'.format(encoded_image),
        xref="paper", yref="paper",
        x=0, y=1,
        sizex=1, sizey=1,
        sizing="stretch",
        opacity=1,
        layer="below")],
    title="Baseball Hits Spray Chart",
    xaxis=dict(title='Horizontal Coordinate', showgrid=False, zeroline=False),
    yaxis=dict(title='Vertical Coordinate', showgrid=False, zeroline=False, autorange='reversed', scaleanchor="x", scaleratio=1),
    showlegend=True,
    plot_bgcolor='white',
    width=700,  # 그래프 크기 설정 (정사각형 형태)
    height=700
)

# 그래프 표시
fig.show()

 

하얗게 그려놓은 파울 라인 옆으로 안타로 나오는 타구들이 나오는 것을 알 수 있습니다.
 

이미지 수정하기

그래서 이미지의 상단을 늘린 후 값의 좌표를 수정해 최대한 파울라인 선 안으로 들어가도록 수정해 주었습니다.

from PIL import Image

def adjust_image(image_path, add_top, cut_bottom):
    # 이미지 로딩
    img = Image.open(image_path)
    width, height = img.size
    
    # 새 이미지 크기 설정: 하단을 잘라내고 상단에 공간 추가
    new_height = height + add_top - cut_bottom
    
    # 새 이미지 생성 (검은색으로 채움)
    new_image = Image.new("RGB", (width, new_height), "black")
    
    # 원래 이미지를 새 이미지에 붙여넣기
    # 이미지의 상단을 높이므로, 붙여넣기 시작 위치의 y좌표는 추가할 높이
    new_image.paste(img, (0, add_top))

    # 하단을 자르기 위해, 붙여넣은 이미지의 하단 부분 잘라내기
    new_image = new_image.crop((0, 0, width, new_height))
    
    # 변경된 이미지 저장
    modified_image_path = image_path.replace('.png', '_modified.png')
    new_image.save(modified_image_path)
    
    return modified_image_path

# 이미지 파일 경로 및 조정할 높이 값
image_path = '이미지'
add_top = 50  # 상단에 추가할 높이
cut_bottom = 30  # 하단에서 자를 높이

# 이미지 조정
modified_image_path = adjust_image(image_path, add_top, cut_bottom)

 
이제 그래프를 출력해 보겠습니다.

모든 안타들이 그라운드 안으로 들어온 것을 볼 수 있습니다.
 
데이터 중 안타나 2루타보다 홈런이 더 앞에 측정되어 있는 것들을 볼 수 있습니다. 이는 메이저리그 구장들이 위의 이미지처럼 대칭을 이루고 있지 않아서 나오는 값들입니다.
 
그저께나도의 히트 스프레이 차트를 확인해보았는데 아레나도만 하기에는 아까워서 애런 저지, 오타니 쇼헤이, 멧 올슨, 김하성 선수의 히트 스프레이 차트도 그려보았습니다.
 

애런 저지 히트 스프레이 차트

플레이어 ID만 바꿔주면 되기 때문에 애런 저지 선수의 ID인 592450을 넣고 만들어 보았습니다.
 

오타니 쇼헤이 히트 스프레이 차트

플레이어 ID만 바꿔주면 되기 때문에 오타니 쇼헤이 선수의 ID인 660271을 넣고 만들어 보았습니다.

멧 올슨 히트 스프레이 차트

플레이어 ID만 바꿔주면 되기 때문에 멧 올슨 선수의 ID인 621566을 넣고 만들어 보았습니다.

김하성 히트 스프레이 차트

플레이어 ID만 바꿔주면 되기 때문에 김하성 선수의 ID인 673490을 넣고 만들어 보았습니다.

반응형

'야구 분석/Python'의 다른글

  • 현재글 히트 스프레이 차트에 야구장 사진 넣어보기

관련글