2025.03.21 본_캠프 23일차

민동·2025년 3월 21일
1

본캠프

목록 보기
24/74
post-thumbnail

오늘은 games_detail.csv랑 games.csv 데이터를 전처리 하는 과정을 거쳤다.
오늘 하루종일 전처리를 진행했고 오후 8시쯤에 서로의 쿼리를 비교했다.

  1. 서부/동부별 합쳐서 팀 상위 5개 팀이랑 우리가 선정한 팀을 비교하여 승패 및 각종 지표 확인
    1. 칼럼별 이상치,결측치 제거하기 : games_detail.csv의 min,pf 칼럼 결측치 제거, 이상치 제거, 데이터 형태 통합. ex. 00:00
    2. data는 2014시즌 ~ 2022시즌
    3. games_detail.csv를 GAME_ID,TEAM_ID로 그룹화 한 뒤, games.csv랑 병합? (단.pct는 제외)
    4. 포지션 별 선수 스탯 분석( 한판 전체 시간의 5% 미만인 사람들은 제외?? 기준 세울 필요 있음! )
  2. 선수 스탯 별 가성비 확인(선수의 연봉과, 나이 추가 필요) + 제한된 샐러리캡내에 운용할수 있는 선수들 확인 > 돈 많이 받는 선수가 돈값을 잘 하는지, 돈 적게 받아도 쏠쏠한지 중요 +대부분의 강팀의 에이스들은 샐러리캡에서 맥스로 줄 수 있는 값을 받음.
  3. 원정이랑 홈경기때 선수 기량 차이 확인??
  4. 에이스 선수 판별 기준을 정할 필요 있음!
  • 효원님 코드
# games 전처리 
# eda 전 shape
games.shape # (26651, 21)
# 2014 이상 시즌만 필터링
games_eda = games[games["SEASON"] >= 2014]  # shape (11420, 21)

# games_eda.isnull().sum() 결측치 전부 0

# 필요없는 컬럼 drop
games_eda = games_eda.drop(['GAME_STATUS_TEXT','TEAM_ID_home','TEAM_ID_away','FG_PCT_home', 'FT_PCT_home', 'FG3_PCT_home', 'FG_PCT_away', 'FT_PCT_away', 'FG3_PCT_away'],axis=1) 

# eda 후 테이블 확인
games_eda.shape # (11420, 12)

# games_details 전처리
# eda 전 shape
games_details.shape # (668628, 29)

# 2014 시즌 이후의 데이터만 필터링
games_details_eda = games_details[games_details['GAME_ID'].isin(games_eda['GAME_ID'])] # (299361, 29)

# null값 있는 데이터 삭제 (nickname, start_position, commnet 제외)
games_details_eda = games_details_eda.dropna(subset=['MIN','FGM','FGA']) # (246071, 29)

# 필요없는 컬럼 삭제
games_details_eda = games_details_eda.drop(['NICKNAME','COMMENT','FG_PCT','FG3_PCT','FT_PCT','PLUS_MINUS'], axis=1) # (246071, 23)

games_details_eda.shape

# MIN 형태 통일
# : 로 연결되어있는 숫자의 소수점 제거하는 함수
def min_form_1(x):
    a, b = x.split(':')
    a = int(float(a))
    b = int(float(b))
	return f'{a:02d}:{b:02d}'

# float형태를 시간형태로 변경
def min_form_2(x):
    a = float(x)
    b = int(x)
    c = a-b
    d = int(c*60)
    
	return f"{b:02d}:{d:02d}"
# ':' 가 있을 때 min_form_1(x), '.' 가 있을 때 min_form_2(x)
games_details_eda['MIN'] = games_details_eda['MIN'].apply(
    lambda x: min_form_1(x) if isinstance(x, str) and ':' in x 
    else min_form_2(x) if isinstance(x, str) and '.' in x 
    else None
)

# 시간형태을 다시 00.00분 형태로 변경
games_details_eda['MIN'] = (pd.to_timedelta("00:" + games_details_eda['MIN']).dt.total_seconds()/60).round(2)
  • 현석님 코드
###본판###
import pandas as pd
import numpy as np
import time
from PIL import Image
import altair as alt
import seaborn as sns
import matplotlib.pyplot as plt
pd.set_option('display.max_rows', 1000)
pd.set_option('display.min_rows', 500)


ranking = pd.read_csv('/Users/ronny/Documents/data_visualization_lecture/basic_project/ranking.csv')
gd = pd.read_csv('/Users/ronny/Documents/data_visualization_lecture/basic_project/games_details.csv')
game = pd.read_csv('/Users/ronny/Documents/data_visualization_lecture/basic_project/games.csv')
#player = pd.read_csv('/Users/ronny/Documents/data_visualization_lecture/basic_project/players.csv')
#teams = pd.read_csv('/Users/ronny/Documents/data_visualization_lecture/basic_project/teams.csv')

game = pd.merge(game,gd,how='inner',on='GAME_ID')


ranking['STANDINGSDATE'] = pd.to_datetime(ranking['STANDINGSDATE'] ,infer_datetime_format=True)
ranking['Year'] = ranking['STANDINGSDATE'].dt.year

test = ranking.groupby(['Year', 'TEAM_ID', 'TEAM']).agg({'G':'max','W':'max'}).reset_index()
test['RANK'] = test.sort_values(by = ['Year','W'], ascending=False).groupby('Year')['W'].cumcount()+1
fiveranks = test[(test['RANK']<=5) & (test['Year'] >= 2015)].sort_values(by = ['Year','RANK'],ascending=True).reset_index()



ranking = pd.merge(ranking,fiveranks, how='inner', on=['Year','TEAM_ID','TEAM','G','W'])
plus = ranking[(ranking['RANK']==1) & (ranking['STANDINGSDATE'] == '2017-04-12')]
top_5_rank = pd.concat([ranking.drop_duplicates(subset=['TEAM_ID','TEAM','G','W','L'], keep='last').sort_values(by = ['Year','RANK'],ascending=True),plus]).reset_index()
top_5_rank

#결측치 제거
game = game.dropna(subset=['MIN','FGM','FGA','FG_PCT','FG3M','FG3A','FG3_PCT','FTM','FTA','FT_PCT','OREB','DREB','REB','AST','STL','BLK','TO','PF','PTS']).reset_index()

#필요없는 컬럼 제거
game = game.drop(['GAME_DATE_EST','GAME_STATUS_TEXT','FG_PCT_home','FT_PCT_home','FG3_PCT_home','FG_PCT_away','FT_PCT_away','FG3_PCT_away','TEAM_ABBREVIATION','NICKNAME','COMMENT','FG_PCT','FG3_PCT','FT_PCT','PLUS_MINUS','index'], axis = 1)

#플레이시간이 마이너스인걸 이상치라 생각하고 제외
minus = game[game['MIN'].str.contains('-')].index
game.drop(minus, inplace=True)


# : 를 기준으로 앞 뒤의 숫자를 min1,min2에 나눠 넣어줌.
game[['min1','min2']] = game['MIN'].str.split(':',expand=True)

# min1에 담긴 숫자 중, 1.00000000 같은 float를 1.0 과 같이 1차적으로 바꿔줌 > 바로 정수형으로 안바뀌더라구요...
game['min1'] = pd.to_numeric(game['min1'])
#float형을 int로 바꿔줌.
game['min1'] = game['min1'].astype('int64')

#데이터에 1:60 같은 해괴한 숫자가 있어서, 2:00으로 바꾸기 위해 min3과 min4에 계산한 결과를 넣음. + 계산 중 '00'이 안들어가고 결측치로 나와서 fillna('00')을 넣음.
game['min3'] = game.apply(lambda x: x['min1'] if x['min2']!='60' else x['min1']+1, axis=1)
game['min4'] = game.apply(lambda x: '00' if x['min2']=='60' else x['min2'], axis=1)
game['min4'] = game['min4'].fillna('00')

#test에 min3,min4를 넣고 다시 처음의 min의 형식을 1:30같은 형태로 만들어줌.
test = ['min3','min4']
game['MIN'] = game[test].apply(lambda row: ':'.join(row.values.astype(str)), axis=1)

game['min3'] = game['min3'].astype('int64')
game['min4'] = game['min4'].astype('int64')
#다 사용한 행 지워주기
#game = game.drop(['min1','min2','min3','min4'],axis=1)
  • 내 코드
# games_details 데이터 로드
df2 = pd.read_csv('games_details.csv')
#df2.info() #(668628 , 28)

#MIN 데이터를 통합합
df2['MIN'] = (pd.to_timedelta("00:" + df2['MIN'].astype(str), errors='coerce').dt.total_seconds() / 60).round(2)

#df2의 불필요한 칼럼 제거거
df2_drop = df2.drop(columns=['NICKNAME','COMMENT', 'FG_PCT','FG3_PCT','FT_PCT','PLUS_MINUS'])

#start_position의 nan값을 0으로 변경
df2_drop['START_POSITION'] = df2_drop['START_POSITION'].fillna(0)
df2_drop.head(10)
#df2_drop.info() # (668628 ,23)

#결측치 확인하기
#print(df2.isna().sum())

#결측치 제거하기
df2_na = df2_drop.dropna()
#print(df2_na.isna().sum())
#df2_na.info() #(558938, 23)

# MIN 데이터를 통합합,df2의 불필요한 칼럼 제거,start_position의 nan값을 0으로 변경 한 데이터 저장
games_detail = df2_na.copy()
games_detail

#csv로 저장
games_detail.to_csv('games_details_filtered.csv',index=False)
profile
아자아자

0개의 댓글