EDA Test 3 - 올림픽 데이터 Code Review

솔비·2024년 1월 27일
0
post-thumbnail
post-custom-banner

문제 소개 및 데이터 준비 단계


Data 원본 출처

Target Data(CSV): 역대(1976-2008) 하계 올림픽 메달리스트에 대한 정보
참고사항: 해당 데이터 분석시 한계점
  • 해당 데이터는 공식 데이터(국제스포츠정보센터)와 차이가 있음.
    • 대한민국 데이터 누락예시: 2008년 베이징올림픽 역도 48kg 은메달 임정화 누락
  • 복식/단체 종목의 경우 한 종목에서 여러명이 메달을 획득하지만, 국가 순위 집계시 1개로 집계됨
    • 동일 종목인 경우 1개로 계산하는 것이 용이
    • 단, 3,4위 모두에 동메달을 주는 경우 한 나라에서 동메달 2개 획득시 문제 발생
      - 대한민국 사례: 1992년 바르셀로나 올림픽 실제 탁구 남성복식 2팀 준결승 진출로 및 패배로 동메달 2개 획득
      - 당시 준결승 진출시 동메달 수여, 총 4명
      - -> 이 자료에서는 누가 누구와 복식조를 이뤘는지 구분할 수 없으며 동일종목이므로 이 자료로 국가 순위 집계시 문제 발생
      - 참고: 현재 올림픽 탁구 복식 4위에게는 동메달을 수여하지 않음


  • 올림픽 메달 취소 등 반영 안되어있음
  • 복식/단체 종목의 선수 수, 당시 메달 수여 룰, 메달 취소 및 승격/승계 등의 실제 메타데이터가 없이는 확인 어려움
  • 이러한 이유로 해당 자료 자체만으로 Test 진행 할 예정이며, 국가별 메달 집계시 동일종목당 1개의 메달로 계산





1단계: Load Data & Preprocessing


문제 1-1) Target Data 가져오기 (10점)

  • 위에 제시된 링크 혹은 datas 폴더에 있는 데이터(Summer-Olympic-medals-1976-to-2008.csv)를 Pandas DataFrame으로 읽어 오세요.
    • hint1: 에러 메시지를 확인하세요.
    • hint2: 해당 데이터는 영어로 이루어져 있습니다.

🧷 내 답변

pip install chardet 

import chardet

with open('./datas/Summer-Olympic-medals-1976-to-2008.csv', 'rb') as rawdata:
    result = chardet.detect(rawdata.read(10000))

# check what the character encoding might be
print(result)

➡️ encoding 값 찾기

df_target = pd.read_csv('./datas/Summer-Olympic-medals-1976-to-2008.csv',encoding='ISO-8859-1')

➡️ 데이터 불러오기

read_csv 시 UnicodeDecodeError를 해결하기 위해
chardet 라이브러리를 통해 encoding 값을 알 수 있는 방법을 찾았다.




문제 1-2) Preprocessing: missing data 처리 (10점)

  • 1-1에서 읽은 Data에는 missing data가 있습니다. missing data를 확인하고 처리하세요.
    • 조건1: missing data가 있다면, 해당 row(행)를 삭제(drop)하세요
    • 조건2: Index를 초기화(reset)하고, 기존 Index는 삭제(drop)하세요.

🧷 내 답변

df_target = df_target[df_target['City'].notnull()]
  • 데이터 info() 확인 시

    RangeIndex값과 Non-null Count 값이 달라서
    특정 컬럼에 notnull()한 값을 데이터프레임에 넣어서 해결하였다.
    또는 dropna()를 사용할 수도 있다.
  • 참고링크 : https://blog.naver.com/snowstormaw/222863967632




문제 1-3) Preprocessing: Data Type 정리 (10점)

  • 1-2에서 만든 DataFrame을 아래의 조건에 따라 데이터의 타입을 확인하고 변경해주세요.
    • 조건1: float data는 int로 변경해주세요.
    • 조건2: float data외의 모든 데이터가 string 인지 확인해주세요.

🧷 내 답변

df_target['Year'] = df_target['Year'].astype(int)

info() 확인시 Year데이터만 float64 그외는 object이므로
Year 컬럼만 astype 메서드를 이용해 int로 변경해주었다.





2단계: 원하는 Data로 가공하기


문제 2-1) 2008년 대한민국 메달리스트 찾기 (15점)

  • 문제 1에서 만든 DataFrame을 이용하여 2008년 베이징 올림픽 양궁 종목에서 금메달을 획득한 선수들을 찾아보세요.
    • 조건1: 2008년 베이징 올림픽 양궁 종목의 금메달리스트만 있는 DataFrame을 만들어 주세요
    • 참고: 추후 문제풀이시 문제 없게 하기 위해서 현재데이터를 deep copy하여 진행하시는 것을 추천드립니다.
      • 하지 않아도 문제는 없으나 코드 작성 방법에 따라 다음 문제 풀이시 다시 load하고 전처리 진행해야 할 수도 있습니다.

🧷 내 답변

import copy

df_copy = df_target.copy()

# 2008 베이징 양궁 금메달 + 대한민국
df_archery = df_copy.loc[(df_copy["Medal"] == 'Gold')].loc[(df_copy["Sport"] == "Archery")].loc[(df_copy["City"] == "Beijing")].loc[(df_copy["Year"] == 2008)].loc[(df_copy["Country"] == "Korea, South")]

loc를 활용해 특정 데이터만 가져올 수 있다.




문제 2-2) 대한민국 역대(1976-2008) 하계 올림픽 메달 획득 내역 확인(15점)

  • 문제 1에서 만든 DataFrame과 Pandas 기능을 활용하여 아래 예시와 같은 형태의 대한민국 역대 메달 획득 내역을 만들어주세요.
    • 조건1: Index는 Year - Medal로 보여주세요(아래 예시 참고)
    • 조건2: Index에서 Year는 내림차순, Medal은 Gold-Silver-Bronze 순으로 보여주세요(아래 예시 참고)
    • hint1: 앞서 이야기 한 바와 같이, 메달 숫자는 복식/단체 종목을 감안하여 선수명(Athlete)과 성별(Gender)를 제외한 내용이 일치할 경우 같은 경기에서 획득한 메달로 간주하시면 됩니다.
    • hint2: 내용이 일치하는 데이터를 삭제하기 위한 방법은 drop_duplicate, groupby, pivot_table 등 다양한 방법이 있습니다.
    • hint3: Medal Index의 정렬 순서를 'Gold'-'Silver'-'Bronze'로 하기 위해서 sort_index의 'key' argument에 dictionary를 활용할 수 있습니다.
    • 참고1: 예시와 같이 컬럼명은 City 등 아무 컬럼명이든 상관 없습니다. 하나의 컬럼만 보여주세요.
    • 참고2: 추후 문제풀이시 문제 없게 하기 위해서 현재데이터를 deep copy하여 진행하시는 것을 추천드립니다.
      • 하지 않아도 문제는 없으나 코드 작성 방법에 따라 다음 문제 풀이시 다시 load하고 전처리 진행해야 할 수도 있습니다.
    • 참고3: 대한민국은 1980년 모스크바 올림픽에 참가하지 않았습니다.

🧷 내 답변

# 대한민국 데이터만 추출
df_kor = df_copy.loc[(df_copy["Country"]== "Korea, South")]
# 중복데이터 제거
df_kor = df_kor.drop_duplicates(["City","Year","Sport","Discipline","Event","Country_Code","Country","Event_gender","Medal"])

#피봇테이블
df_kor = df_kor.pivot_table("City",index=["Year","Medal"], aggfunc="count")

#medal = ['Gold','Silver','Bronze']
#df_kor.sort_index(level=["Year","Medal"],ascending=[True,True],key=lambda x: x.map({ k: i for i, k in enumerate(medal)}))

# 각각 정렬
df_kor.sort_index(level=["Year"],ascending=True)
df_kor = df_kor.reindex(["Gold","Silver","Bronze"],level=1)
  1. 중복데이터 삭제를 위해 drop_duplicates() 사용 : https://wikidocs.net/154060
  2. sort_index의 key옵션을 사용하여 메달정렬을 하려 했으나,
    연도를 정렬하면 메달정렬이 안되고, 메달을 정렬하면 연도 정렬이 풀리는... : https://wikidocs.net/153330
  3. 결국 돌고 돌아 reindex로 해결 : https://kongdols-room.tistory.com/163




문제 2-3) 1996년 애틀란타 올림픽 총 메달 개수 기준 상위 10개 국가 확인하기(20점)

  • 문제 1에서 만든 DataFrame과 Pandas 기능을 활용하여 아래 예시와 같은 형태의 메달 개수 기준 상위 10개국 내역을 만들어주세요.
    • 조건1: Index는 앞선 1단계에서 Preprocessing한 Data의 Index 그대로 나두어 주세요.
    • 조건2: 총 메달 개수로 오름차순 정렬 후 상위 10개 국가만 나타내는 DataFrame을 만드세요.
    • 조건3: 결과 DataFrame의 Columns은 ['Country', 'Medal'] 입니다.
    • hint1: 앞서 이야기 한 바와 같이, 메달 숫자는 복식/단체 종목을 감안하여 선수명(Athlete)과 성별(Gender)를 제외한 내용이 일치할 경우 같은 경기에서 획득한 메달로 간주하시면 됩니다.
    • hint2: 내용이 일치하는 데이터를 삭제하기 위한 방법은 drop_duplicate, groupby, pivot_table 등 다양한 방법이 있습니다.
    • hint3: Groupby, Pivot_table 등의 기능을 활용하는 경우 'as_index' 혹은 'index'와 같은 argument를 활용하세요
    • 참고: 추후 문제풀이시 문제 없게 하기 위해서 현재데이터를 deep copy하여 진행하시는 것을 추천드립니다.
      • 하지 않아도 문제는 없으나 코드 작성 방법에 따라 다음 문제 풀이시 다시 load하고 전처리 진행해야 할 수도 있습니다.

🧷 내 답변

# 깊은복사
df_copy = df_target.copy()

# 애틀란타 올림픽 데이터 추출
df_copy = df_copy.loc[(df_copy["City"]== "Atlanta")].loc[(df_copy["Year"] == 1996)]

# 중복 데이터 제거
df_copy = df_copy.drop_duplicates(["City","Year","Sport","Discipline","Event","Country_Code","Country","Event_gender","Medal"])

# country, medal 데이터만 뽑고 / count를 기준으로 group_by().count() / 매달 내림차순으로 정렬
df_rank_10 = df_copy[['Country', 'Medal']].groupby('Country',as_index=False).count().sort_values(by="Medal",ascending=False)

group by 참고링크 : http://www.teddynote.com/pandas/pandas-groupby/




문제 2-4) 1996년 애틀란타 올림픽 금매달 개수 기준 상위 10개 국가 확인하기(20점)

  • 문제 1에서 만든 DataFrame과 Pandas 기능을 활용하여 아래 예시와 같은 형태의 메달 개수 기준 상위 10개국 내역을 만들어주세요.
    • 조건1: 'Gold', 'Silver', 'Bronze' 컬럼을 만들고, 해당 Row(행)의 Medal 이 Gold면 'Gold' 컬럼에 1, Silver면 'Silver' 컬럼에 1, 'Bronze'면 'Bronze'컬럼에 1을 입력하세요
    • 조건2: Index는 앞선 1단계에서 Preprocessing한 Data의 Index 그대로 나두어 주세요.
    • 조건3: 금메달 개수로 내림차순 정렬 후 상위 10개 국가만 나타내는 DataFrame을 만드세요.
      • 만약 금메달 개수가 같다면, 은메달 개수가 많은 국가가 더 높은 순위이며 은메달 개수도 같다면 동메달 개수가 더 많은 국가가 상위입니다.
    • 조건4: 결과 DataFrame의 Columns은 ['Country', 'Gold', 'Silver', 'Bronze'] 입니다.
    • hint1: 앞서 이야기 한 바와 같이, 메달 숫자는 복식/단체 종목을 감안하여 선수명(Athlete)과 성별(Gender)를 제외한 내용이 일치할 경우 같은 경기에서 획득한 메달로 간주하시면 됩니다.
    • hint2: 내용이 일치하는 데이터를 삭제하기 위한 방법은 drop_duplicate, groupby, pivot_table 등 다양한 방법이 있습니다.
    • hint3: Groupby, Pivot_table 등의 기능을 활용하는 경우 'as_index' 혹은 'index'와 같은 argument를 활용하세요

🧷 내 답변

# 컬럼생성
df_copy["Gold"] = np.NaN
df_copy["Silver"] = np.NaN
df_copy["Bronze"] = np.NaN

# 값 채우기
for idx, row in df_copy.iterrows():
    if row["Medal"] == "Gold" :
        df_copy.at[idx,"Gold"] = 1
    elif row["Medal"] == "Silver" :
        df_copy.at[idx,"Silver"] = 1
    elif row["Medal"] == "Bronze" :
        df_copy.at[idx,"Bronze"] = 1
        
#필요컬럼만 뽑아서 / group by().sum()하고 / 정렬 / 10위만 뽑기
df_rank_10 = df_copy[["Country","Gold","Silver","Bronze"]].groupby("Country",as_index=False).sum().sort_values(by=["Gold","Silver","Bronze"], ascending=[False,False,False]).head(10)

at 사용법 : https://devocean.sk.com/blog/techBoardDetail.do?ID=164657&boardType=techBlog





Zero Base 데이터분석 스쿨
Daily Study Note
profile
Study Log
post-custom-banner

0개의 댓글