[EDA] mini project 9 _ 올림픽 금메달 데이터 (drop_duplicates, dropna)

jaam._.mini·2023년 12월 26일
0

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


Data 원본 출처

- Target Data(CSV): 역대(1976-2008) 하계 올림픽 메달리스트에 대한 정보

- 참고사항: 해당 데이터 분석시 한계점

  • 해당 데이터는 공식 데이터(국제스포츠정보센터)와 차이가 있음.

    • 대한민국 데이터 누락예시: 2008년 베이징올림픽 역도 48kg 은메달 임정화 누락
  • 복식/단체 종목의 경우 한 종목에서 여러명이 메달을 획득하지만, 국가 순위 집계시 1개로 집계됨

    • 동일 종목인 경우 1개로 계산하는 것이 용이
    • 단, 3,4위 모두에 동메달을 주는 경우 한 나라에서 동메달 2개 획득시 문제 발생
      • 대한민국 사례: 1992년 바르셀로나 올림픽 실제 탁구 남성복식 2팀 준결승 진출로 및 패배로 동메달 2개 획득
        • 당시 준결승 진출시 동메달 수여, 총 4명
        • -> 이 자료에서는 누가 누구와 복식조를 이뤘는지 구분할 수 없으며 동일종목이므로 이 자료로 국가 순위 집계시 문제 발생
        • 참고: 현재 올림픽 탁구 복식 4위에게는 동메달을 수여하지 않음
  • 올림픽 메달 취소 등 반영 안되어있음

  • 복식/단체 종목의 선수 수, 당시 메달 수여 룰, 메달 취소 및 승격/승계 등의 실제 메타데이터가 없이는 확인 어려움

  • 이러한 이유로 해당 자료 자체만으로 Test 진행 할 예정이며, 국가별 메달 집계시 동일종목당 1개의 메달로 계산








1. Load Target Data


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

위에 제시된 링크 혹은 datas 폴더에 있는 데이터(Summer-Olympic-medals-1976-to-2008.csv)를 Pandas DataFrame으로 읽어 오세요.

📌 encoing='utf-8' 에러 발생

  • df_target = pd.read_csv('./datas/Summer-Olympic-medals-1976-to-2008.csv', encoding='utf-8')
  • → UnicodeDecodeError: 'utf-8' codec can't decode byte 0xd6 in position 136: invalid continuation byte'ArithmeticError'
    • 이 에러는 읽어드릴 파일의 포맷이 UTF-8이 아니기 때문에 발생한다. 

💡encoding = latin-1 로 해결

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

  • 참고

# 1-1

import pandas as pd
import numpy as np

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




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

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



📌 NaN 값 확인

df_target.info()

📌 NaN값 삭제

  • NaN이 하나라도 있는 행으르 삭제 할 것 : (how=any)
  • NaN으로 가득 찬 행만 삭제 : (how=all)

💡 dropna()

  • dropna( )의 기본값(default)은 how = any라 NaN이 하나만 있어도 그 행은 삭제된다.
  • 참고
  • 참고
    • .dropna(axis=1) : NaN 포함 컬럼 제거
    • .dropna(axis=0) : NaN 포함 행 제거
    • .drop('col2', axis=1) : 한 행씩(axis=1) 진행하면서 'col2'이름을 가진 열 삭제
df_target.dropna(inplace=True)
df_target.info()
df_target.tail(2)

📌 reset_index()

df_target = df_target.reset_index()
df_target.tail(2)

del df_target['index']
df_target.tail(2)




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

  • 1-2에서 만든 DataFrame을 아래의 조건에 따라 데이터의 타입을 확인하고 변경해주세요.
    • 조건1: float data는 int로 변경해주세요.
    • 조건2: float data외의 모든 데이터가 string 인지 확인해주세요.
  • 완료 후 결과 dataframe 변수를 check_01_03 함수에 입력하여 채점하세요.

📌 float -> int

# 나머지 데이터는 처음부터 string

df_target['Year'] = df_target['Year'].astype('int64')
df_target.info()









2. 원하는 Data로 가공하기


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

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

📌 deep copy

import numpy as np
import copy
copy_df_target = df_target.copy()

📌 dataframe

a = copy_df_target['Year'] == 2008
b = copy_df_target['City'] == 'Beijing'
c = copy_df_target['Sport'] == 'Archery'
d = copy_df_target['Medal'] == 'Gold'
e = copy_df_target['Country_Code'] == 'KOR'

df_archery = copy_df_target[a & b & c & d & e]
df_archery.info()
df_archery.tail()




문제 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를 활용할 수 있습니다.
      • 이 외에 sort_index의 다른 arguments도 확인해 보세요

📌drop_duplicates (중복행 제거)

  • drop_duplicates메서드는 내용이 중복되는 행을 제거하는 메서드
  • 참고
  • 기본 사용법
    • df.drop_duplicates(subset=None, keep='first', inplace=False, ignore_index=False)
    • subset : 중복값을 검사할 열 입니다. 기본적으로 모든 열을 검사합니다.
    • keep : {first / last} 중복제거를할때 남길 행입니다. first면 첫값을 남기고 last면 마지막 값을 남깁니다.
    • inplace : 원본을 변경할지의 여부입니다.
    • ignore_index : 원래 index를 무시할지 여부입니다. True일 경우 0,1,2, ... , n으로 부여됩니다.

💡drop_duplicates(subset =

  • subset에 입력된 컬럼명을 기준으로 해당 컬럼의 중복값을 검사하게됩니다.
  • subset이 따로 입력되지 않는 경우는 모든 열에대해 값이 중복인 행을 제거합니다.
  • subset에 특정 컬럼명만 입력할 경우, 해당 열에대해서만 중복값 검사를 수행합니다.
  • subset에 리스트를 입력할 경우 해당 열들에대해서 모두 중복인 경우만 삭제를 진행합니다.
import copy

df_kor = df_target.copy()
df_kor = df_target[df_target['Country_Code'] == 'KOR']
df_kor = df_kor.drop_duplicates(subset = ['City','Year', 'Sport', 'Discipline',
                                       'Event', 'Country_Code', 'Country',
                                       'Event_gender', 'Medal'])
df_kor.tail(2)

💡 reindex()

  • [참고] https://kongdols-room.tistory.com/163

  • 인덱스 정렬(순서변경)을 위한 메서드

  • 특정 축을 따라 입력된 레이블 배열에 따라 데이터 순서를 조정

    • 기존에 존재하는 데이터에 레이블의 새로운 세트에 매치해 순서를 재조정
    • 컬럼은 있지만, 데이터가 없는 레이블에 NaN값을 마커 가능(없는 데이터를 채움)
  • Series

    • result = object.reindex(index, method=None, fill_value=np.nan, limit=None)
  • DataFrame

    • result = object.reindex(index, columns, axis=0, method=None, fill_value=np.nan, linit=None)
      • object : 데이터 재정렬 객체
      • index : 정렬 순서로 구성된 인덱스 배열
      • method : index가 object에 없는 경우 해당 값을 채우는 [방식]
      • fill_value : index가 object에 없는 경우 해당 값을 채우는 [값]
      • limit : NaN이 여러개인 경우, method 방식에 따라 누락 값을 채우는 개수 제한
      • axis : 정렬 수행 축 값(정렬 기준)
        • index / 0 : 행에 대해서 정렬
        • columns / 1 : 열에 대해서 정렬
  • level : 멀티인덱스에서 이름을 바꿀 레벨을 지정하는 인자

df_kor = df_kor.pivot_table(index=['Year', 'Medal'], values = 'City', aggfunc='count')
df_kor = df_kor.reindex(['Gold', 'Silver', 'Bronze'], level=1)
df_kor




문제 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를 활용하세요
# 1996년
# 상위 10개 국가만 나타내는 DataFrame
# column = Country, Medal
# 총 매달 개수

import copy
df_rank = df_target.copy()
df_rank = df_rank[df_rank['Year']==1996]
df_rank = df_rank.drop_duplicates(subset = ['City','Year', 'Sport', 'Discipline',
                                       'Event', 'Country_Code', 'Country',
                                       'Event_gender', 'Medal'])
df_rank = pd.pivot_table(df_rank, index='Country', values='Medal', aggfunc='count')
df_rank

df_rank = df_rank.reset_index()
df_rank.sort_values('Medal', ascending=False, inplace=True)
df_rank_10 = df_rank.head(10)
df_rank_10




문제 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를 활용하세요
# 1996년
# 금메달 개수 확인
# 상위 10개국 

import copy
df_rank = df_target.copy()
df_rank[['Gold', 'Silver', 'Bronze']] = 0
df_rank.tail(1)

df_rank = df_rank[(df_rank['Year'] == 1996) & (df_rank['City'] == 'Atlanta')]
df_rank = df_rank.drop_duplicates(subset = ['City','Year', 'Sport', 'Discipline',
                                       'Event', 'Country_Code', 'Country',
                                       'Event_gender', 'Medal'])

df_rank = df_rank.reset_index()

df_rank.info()
df_rank.tail(1)

del df_rank['index']

for idx in range(0, len(df_rank)):
    if df_rank['Medal'].loc[idx] == 'Gold':
        df_rank['Gold'].loc[idx] += 1
    elif df_rank['Medal'].loc[idx] == 'Silver':
        df_rank['Silver'].loc[idx] += 1
    elif df_rank['Medal'].loc[idx] == 'Bronze':
        df_rank['Bronze'].loc[idx] += 1

df_rank.tail(2)

📌 groupby.agg

  • 참고
  • groupby 메서드는 데이터를 그룹화하여 연산을 수행하는 메서드
  • 기본 사용법
    • by : 그룹화할 내용입니다. 함수, 축, 리스트 등등이 올 수 있습니다.
    • axis : 그룹화를 적용할 축입니다.
    • level : 멀티 인덱스의 경우 레벨을 지정할 수 있습니다.
    • as_index : 그룹화할 내용을 인덱스로 할지 여부입니다. False이면 기존 인덱스가 유지됩니다.
    • sort : 그룹키를 정렬할지 여부입니다.
    • group_keys : apply메서드 사용시 결과에따라 그룹화 대상인 열이 인덱스와 중복(group key)이 될 수 있습니다. 이 때, group_keys=False로 인덱스를 기본값으로 지정할 수 있습니다.
    • squeeze : 결과가 1행 or 1열짜리 데이터일 경우 Series로, 1행&1열 짜리 데이터일 경우 스칼라로 출력합니다.
    • observed : Categorical로 그룹화 할 경우 Categorical 그룹퍼에 의해 관찰된 값만 표시할 지 여부입니다.
    • dropna : 결측값을 계산에서 제외할지 여부입니다.
  • groupby.agg
df_rank = df_rank.groupby('Country').agg({'Gold': 'sum', 'Silver': 'sum', 'Bronze': 'sum'}).reset_index()
df_rank = df_rank.sort_values(by=['Gold', 'Silver', 'Bronze'], ascending=False)
df_rank = df_rank[['Country','Gold', 'Silver', 'Bronze']]
df_rank_10 = df_rank.head(10)
df_rank_10


제로베이스 데이터 스쿨
profile
비전공자의 데이터 공부법

0개의 댓글