총 2단계 데이터 분석 상황 제시
총점 100점
1단계 DataFrame 불러오기 & 전처리
2단계 DataFrame 가공하기
Data 정보: 역대(1976-2008) 하계 올림픽 메달리스트에 대한 정보
encoding="latin1"
유럽권에서는 알파벳으로 표현하지못하거나 기호가 섞여있는 문자들이 있다.
그러나 이들을 다 포함해도 1바이트를 넘지 않았는데 그 이유는 기존의 ascii는 1바이트(8비트)가 아닌 7비트 였으므로
128가지의 여유공간이 남아있었다. 이 여유공간을 마저 활용해서 만든것이 바로 latin1
1-1에서 읽은 Data에는 missing data가 있습니다. missing data를 확인하고 처리하세요.
- 조건1: missing data가 있다면, 해당 row(행)를 삭제(drop)하세요
- 조건2: Index를 초기화(reset)하고, 기존 Index는 삭제(drop)하세요.
missing data: 결측치
조건1 - missing data의 해당 row(행)를 삭제(drop)
df_target.dropna()
df_target.reset_index(inplace=True)
del df_target["index"]
df_target["Year"] = df_target["Year"].astype("int")
df_target.info()
파이썬 데이터 타입에서 string이 object!
나머지 데이터는 처음부터 string
dtype: 설명
int64: 정수형
float64: 실수형
bool: 부울형
datetime64: 날짜표현
category: 카테고리
object: 문자열 or 복합형
=> 파이썬 data type에서는 string이 없다!
cf) SettingWithCopyWarning 경고 - 뻘짓함
SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead
발생 이유
: 원천 DataFrame로 구성된 파생 DataFrame에 변경을 하는 경우 발생한다.
> (Pandas에서는 원천 DataFrame을 생성할 때만 메모리를 할당하고 이로부터 파생되는 DataFrame은 원천 DataFrame을 이미 적재된 메모리에 접근케 하며 이로 인해 메모리를 절약합니다. 원천 DataFrame의 부분집합(subset)에 view를 형성한다 보면 됩니다.)
> 실제 개발하는 사람의 의도에 따라 원하는 바가 다를 수 밖에 없습니다. Pandas에서는 파생 DataFrame에 수정을 가하는 것을 권장하지 않습니다.(그래서 경고를 띄우는 것이죠.) 대신 Pandas는 copy() 메서드를 통해 파생 DataFrame에 독립적인 메모리를 부여한 뒤 여기에 수정을 가하도록 유도하지요. view를 실질화(materialization)시키는 것이죠.
> 요컨대 SettingWithCopyWarning의 발생을 예방하기 위한 가장 쉬운 방법은 파생 DataFrame에 copy() 메서드를 실행해, 원천 DataFrame과 별도인 메모리 공간을 파생 DataFrame에 부여하는 것입니다. 원천과 파생이 완전히 갈라서는 것이지요.
=> SettingWithCopyWarning의 발생을 예방하기 위한 가장 쉬운 방법은 파생 DataFrame에 copy() 메서드를 실행해, 원천 DataFrame과 별도인 메모리 공간을 파생 DataFrame에 부여하는 것
출처: https://emilkwak.github.io/pandas-dataframe-settingwithcopywarning
cf) archery - 양궁
주최년도가 2008년인 데이터 확인
# 주최년도 유니크한 값 확인
df_target['Year'].unique()
# 주최년도가 2008년인 데이터 확인
df_target[df_target['Year']==2008]
주최년도가 2008년이고, 주최국가 베이징(Beijing)인 데이터 확인
# 주최국도 유니크한 값 확인
df_target['City'].unique()
# 주최년도가 2008년이고, 주최국가 베이징(Beijing)인 데이터 확인
df_target[(df_target['Year']==2008) & (df_target['City']=='Beijing')]
주최년도가 2008년이고, 주최국가 베이징(Beijing)이고, 종목이 양궁인 데이터 확인
# 종목의 유니크한 값 확인
df_target['Sport'].unique()
# 주최년도가 2008년이고, 주최국가 베이징(Beijing)이고, 종목이 양궁인 데이터 확인
df_target[(df_target['Year']==2008) & (df_target['City']=='Beijing') & (df_target['Sport']=='Archery')]
주최년도가 2008년이고, 주최국가 베이징(Beijing)이고, 종목이 양궁이고, 메달이 금메달리스트인 데이터 확인
# 메달의 유니크한 값 확인
df_target['Medal'].unique()
# 주최년도가 2008년이고, 주최국가 베이징(Beijing)이고, 종목이 양궁이고, 메달이 금메달리스트인 데이터 확인
df_target[
(df_target['Year']==2008) &
(df_target['City']=='Beijing') &
(df_target['Sport']=='Archery') &
(df_target['Medal']=='Gold')
]
주최년도가 2008년이고, 주최국가 베이징(Beijing)이고, 종목이 양궁이고, 메달이 금메달리스트인 데이터 확인
# 우승국가의 유니크한 값 확인
df_target['Country'].unique()
# 주최년도가 2008년이고, 주최국가 베이징(Beijing)이고, 종목이 양궁이고, 메달이 금메달리스트인 데이터 확인
# + 2008년 대한민국 리스트 찾기 => 우승국가가 대한민국인 것 찾기
df_target[
(df_target['Year']==2008) &
(df_target['City']=='Beijing') &
(df_target['Sport']=='Archery') &
(df_target['Medal']=='Gold') &
(df_target['Country']=='Korea, South')
]
# 참고사항 - 현재 데이터 깊은 복사(deep copy) => .copy() 사용
df_archery = df_target.copy()
# 조건1 - 2008년 베이징 올림픽 양궁 종목의 금메달리스트만 있는 DataFrame 만들기 (2008년 메달리스트인 한국)
df_archery =df_archery[
(df_archery['Year']==2008)&
(df_archery['City']=='Beijing') &
(df_archery['Sport']=='Archery') &
(df_archery['Medal']=='Gold') &
(df_archery['Country']=='Korea, South')
]
cf) 판다스의 깊은 복사, 얕은 복사
데이터프레임의 복사본(앞에서 말한 파생 DataFrame?)을 만들어 주는 것으로 pandas.DataFrame.copy로 사용함. 이는 당시의 데이터프레임 상태만 복사함.
a = b로 원본 데이터가 변경되면 똑같이 변경됨
df_target['Country'].unique()
문제 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도 확인해 보세요
- 참고1: 예시와 같이 컬럼명은 City 등 아무 컬럼명이든 상관 없습니다. 하나의 컬럼만 보여주세요.
-참고2: 추후 문제풀이시 문제 없게 하기 위해서 현재데이터를 deep copy하여 진행하시는 것을 추천드립니다.
- 하지 않아도 문제는 없으나 코드 작성 방법에 따라 다음 문제 풀이시 다시 load하고 전처리 진행해야 할 수도 있습니다.
- 참고3: 대한민국은 1980년 모스크바 올림픽에 참가하지 않았습니다.
메달 획득 국가가 대한민국인 데이터프레임 생성 - 454개
df_target2 = df_target[df_target['Country']=='Korea, South'] # 454개
df_target2
df_medal = df_target2[df_target2.duplicated(subset=['City', 'Year', 'Sport', 'Discipline', 'Event', 'Country_Code', 'Country', 'Event_gender', 'Medal'])]
df_medal
import numpy as np
# 메달 획득 국가가 대한민국인 데이터프레임 생성 - 454개
df_target2 = df_target[df_target['Country']=='Korea, South']
# 선수명(Athlete)과 성별(Gender)를 제외한 내용이 일치하는 데이터 확인 - 252개
df_target2=df_target2.drop_duplicates(['City', 'Year', 'Sport', 'Discipline', 'Event', 'Country_Code', 'Country', 'Event_gender', 'Medal'])
df_target2 # 중복행 제거하면 202개여야 함
df_target3 = df_target2.pivot_table(index=["Year", "Medal"], values="City", aggfunc='count', sort=True)
df_target3
# df_target3.reindex(['Gold', 'Silver', 'Bronze'], level=1) # levle=1 => 인덱스 재정렬을 적용할 칼럼 번호
# 메달 획득 국가가 대한민국인 데이터프레임 생성 - 454개
df_target2 = df_target[df_target['Country']=='Korea, South'].copy()
# 선수명(Athlete)과 성별(Gender)를 제외한 내용이 중복되는 행 확인 - 252개
df_target2=df_target2.drop_duplicates(['City', 'Year', 'Sport', 'Discipline', 'Event', 'Country_Code', 'Country', 'Event_gender', 'Medal'])
# Index는 Year - Medal인 대한민국 역대 메달 획득 내역
df_kor = df_target2.pivot_table(index=["Year", "Medal"], values="City", aggfunc='count', sort=True)
df_kor = df_kor.reindex(['Gold', 'Silver', 'Bronze'], level=1) # levle=1 => 재정렬하려는 칼럼의 번호
중복행 확인 (duplicated)
DataFrame.duplicated(subset=None, keep='first')
duplicated 메서드: 중복되는 행을 확인하는 메서드
subset : 특정 열만을 대상
행의 모든 요소가 동일한 행이 이미 존재할경우 해당 행은 True로 반환
aggfunc에는 다양한 집계함수들이 올 수 있음
집계 함수 코드 비고
합계 aggfunc = np.sum() numpy 활용
평균 aggfunc = np.mean() numpy 활용
표준편차 aggfunc = 'std' string으로 선언
count aggfunc = 'count' string으로 선언
distinct count aggfunc = 'nunique' string으로 선언
출처: https://data-marketing-bk.tistory.com/entry/Python-Pandas%EC%9D%98-Pivot-Table-%ED%99%9C%EC%9A%A9-%EB%A7%88%EC%8A%A4%ED%84%B0%ED%95%98%EA%B8%B0
: index or columns 기준으로 정렬
multi index를 설정하고 싶을 때는 index = ['col1', 'col2']
출처: https://m.blog.naver.com/gozomi/223009103548
DataFrame.reindex([index], level=?)
index: 재정렬하려는 인덱스 리스트
levle: 재정렬하려는 칼럼 번호
출처: https://kongdols-room.tistory.com/163
문제 1에서 만든 DataFrame과 Pandas 기능을 활용하여 아래 예시와 같은 형태의 총 메달 개수 기준 상위 10개국 내역을 만들어주세요.
- 조건1: Index는 앞선 1단계에서 Preprocessing한 Data의 Index 그대로 나두어 주세요.
- 조건2: 총 메달 개수로 오름차순 정렬 후 상위 10개 국가만 나타내는 DataFrame을 만드세요.
-조건3: 결과 DataFrame의 Columns은 ['Country', 'Medal'] 입니다.
- 예시: 1992년 바르셀로나 올림픽 총 메달 개수에 따른 상위 10개 국가
- hint1: 앞서 이야기 한 바와 같이, 메달 숫자는 복식/단체 종목을 감안하여 선수명(Athlete)과 성별(Gender)를 제외한 내용이 일치할 경우 같은 경기에서 획득한 메달로 간주하시면 됩니다.
- hint2: 내용이 일치하는 데이터를 삭제하기 위한 방법은 drop_duplicate, groupby, pivot_table 등 다양한 방법이 있습니다.
- hint3: Groupby, Pivot_table 등의 기능을 활용하는 경우 'as_index' 혹은 'index'와 같은 argument를 활용하세요
- 참고: 추후 문제풀이시 문제 없게 하기 위해서 현재데이터를 deep copy하여 진행하시는 것을 추천드립니다.
- 하지 않아도 문제는 없으나 코드 작성 방법에 따라 다음 문제 풀이시 다시 load하고 전처리 진행해야 할 수도 있습니다.
1996년 아틀란타 올림픽 정보만 가져옴 - 1859개
df_rank = df_target.copy()
df_rank = df_rank[
(df_rank['Year']==1996)
]
df_rank
df_rank=df_rank.drop_duplicates(['City', 'Year', 'Sport', 'Discipline', 'Event', 'Country_Code', 'Country', 'Event_gender', 'Medal'])
df_rank
df_rank_10 = df_rank.groupby(['Country'], as_index=False)['Medal'].count()
df_rank_10
# cf) as_index=False 를 할 경우 기존 인덱스의 유지가 가능함.
df_rank_10 = pd.DataFrame(df_rank_10)
df_rank_10
df_rank_10 = df_rank_10.sort_values(by='Medal', ascending=True)
df_rank_10
df_rank_10 = df_rank_10.nlargest(10, 'Medal', keep='last')
df_rank_10
# 1996년 아틀란타 올림픽 정보만 가져옴 - 1859개
df_rank = df_target.copy()
df_rank = df_rank[df_rank['Year']==1996]
# 선수명(Athlete)과 성별(Gender)를 제외한 내용이 중복되는 행 제거 - 841개
df_rank=df_rank.drop_duplicates(['City', 'Year', 'Sport', 'Discipline', 'Event', 'Country_Code', 'Country', 'Event_gender', 'Medal'])
# 조건3 - 결과 DataFrame의 Columns ['Country', 'Medal'] 만 뽑기 위해
df_rank_10 = df_rank.groupby(['Country'], as_index=False)['Medal'].count()
# 앞에서 countrt, medal 칼럼 뽑은 거 데이터프레임으로 생성
df_rank_10 = pd.DataFrame(df_rank_10)
# 조건2 - 총 메달 개수로 오름차순 정렬 1 (정렬 sort_values(by='칼럼명') 시용, ascending=True 오름차순)
df_rank_10 = df_rank_10.sort_values(by='Medal', ascending=True)
# 조건 2 - 앞에서 오름차순으로 정렬 후, 상위 10개 국가만 나타내는 DataFrame 2
df_rank_10 = df_rank_10.nlargest(10, 'Medal', keep='last')
check_02_03(df_rank_10)
n : 하위로 나타낼 데이터의 개수
keep='last' : 하위의 데이터로 설정
데이터프레임.nlargest(n, 칼럼명, keep='first')
문제 1에서 만든 DataFrame과 Pandas 기능을 활용하여 아래 예시와 같은 형태의 금메달 개수 기준 상위 10개국 내역을 만들어주세요.
- 조건1: 'Gold', 'Silver', 'Bronze' 컬럼을 만들고, 해당 Row(행)의 Medal 이 Gold면 'Gold' 컬럼에 1, Silver면 'Silver' 컬럼에 1, 'Bronze'면 'Bronze'컬럼에 1을 입력하세요
- 추후 아래 예시와 같은 형태로 DataFrame을 만들기 위한 작업입니다. 적당한 순서에 맞추어 해당 작업을 하시면 되고, 혹시 이 작업이 필요 없을 경우 안하셔도 무방합니다.
- 조건2: Index는 앞선 1단계에서 Preprocessing한 Data의 Index 그대로 나두어 주세요.
- 조건3: 금메달 개수로 내림차순 정렬 후 상위 10개 국가만 나타내는 DataFrame을 만드세요.
만약 금메달 개수가 같다면, 은메달 개수가 많은 국가가 더 높은 순위이며 은메달 개수도 같다면 동메달 개수가 더 많은 국가가 상위입니다.
- 조건4: 결과 DataFrame의 Columns은 ['Country', 'Gold', 'Silver', 'Bronze'] 입니다.
- 예시: 1992년 바르셀로나 올림픽 총 메달 개수에 따른 상위 10개 국가
hint1: 앞서 이야기 한 바와 같이, 메달 숫자는 복식/단체 종목을 감안하여 선수명(Athlete)과 성별(Gender)를 제외한 내용이 일치할 경우 같은 경기에서 획득한 메달로 간주하시면 됩니다.
hint2: 내용이 일치하는 데이터를 삭제하기 위한 방법은 drop_duplicate, groupby, pivot_table 등 다양한 방법이 있습니다.
hint3: Groupby, Pivot_table 등의 기능을 활용하는 경우 'as_index' 혹은 'index'와 같은 argument를 활용하세요
조건3: 금메달 개수로 내림차순 정렬 후 상위 10개 국가만 나타내는 DataFrame을 만드세요.
만약 금메달 개수가 같다면, 은메달 개수가 많은 국가가 더 높은 순위이며 은메달 개수도 같다면 동메달 개수가 더 많은 국가가 상위입니다.
df_rank20 = df_rank20.sort_values(by='Gold', ascending=False)
df_rank20 = df_rank20.nlargest(10, 'Gold', keep="first")
df_rank20
2-4
# 1996년 아틀란타 올림픽 정보만 가져옴 - 1859개
df_rank2 = df_target.copy()
df_rank2 = df_rank[df_rank['Year']==1996]
# df_rank2 = df_rank2[(df_rank['Year']==1996) & (df_target2['City'] == 'Atlanta')]
# 선수명(Athlete)과 성별(Gender)를 제외한 내용이 중복되는 행 제거 - 841개
df_rank2=df_rank2.drop_duplicates(['City', 'Year', 'Sport', 'Discipline', 'Event', 'Country_Code', 'Country', 'Event_gender', 'Medal'])
df_rank2['Gold'] = 0
df_rank2['Silver'] = 0
df_rank2['Bronze'] = 0
for i in range(len(df_rank2)):
if df_rank2.iloc[i, -4] == 'Gold':
df_rank2.iloc[i, -3] += 1
if df_rank2.iloc[i, -4] == 'Silver':
df_rank2.iloc[i, -2] += 1
if df_rank2.iloc[i, -4] == 'Bronze':
df_rank2.iloc[i, -1] += 1
# 피벗테이블 생성
df_rank2 = df_rank2.pivot_table(index='Country', values=['Gold', 'Silver', 'Bronze'], aggfunc='sum')
df_rank2 = df_rank2.groupby('Country').agg({'Gold':sum, 'Silver':sum, 'Bronze':sum}).reset_index()
df_rank2 = df_rank2.sort_values(by=['Gold', 'Silver', 'Bronze'], ascending=False)
df_rank_10 = df_rank2.nlargest(10, 'Gold', keep="first")
check_02_04(df_rank_10)
: 여러개의 열에 여러가지 함수를 적용할 수 있음.
모든열에 여러 함수를 매핑 : group객체.agg([함수1,함수2,함수3,…])
각 열마다 다른 함수를 매핑 : group객체.agg({‘열1’: 함수1, ‘열2’:함수2, …})
print(grouped.agg(['min','max']))
출처: https://yganalyst.github.io/data_handling/Pd_13/
: 인덱스 열로 변환
self.reset_index(level=None, drop=False, inplace=False, col_level=0, col_fill='')
level : Multi Index의 경우 제거할 인덱스의 레벨을 설정할수 있습니다. 기본적으로 모든 레벨
drop : 제거한 인덱스를 열에 추가할지 여부입니다. 기본값은 False로 제거된 인덱스는 열로 변환됨.
inplace : pandas 공통 인수로, 원본을 변경할지 여부
col_level / col_fill : Multi Index의 경우 제거된 인덱스를 열에 추가할 때 레벨과 열의 이름을 설정할 수 있음.
col_level을 통해 레벨을 설정하고, col_fill을통해 해당 열의 이름을 정함.
출처: https://wikidocs.net/155404