제로베이스_데이터분석취업스쿨
파이썬 기초 챕터01~25
(Getting & Knowing Data, Filtering & Sorting, Grouping, Apply, Map, Time_Series, Pivot, Merge, Concat, Statistics, Series & DataFrame, Visualization, Deleting, Data Handling, Data Visualization, Data Analysis & Modeling)
최근 ADSP, 경영정보시각화 등 데이터 자격증 공부를 할 때 배운 개념들과 큰 연관이 있었다.
파이썬은 데이터분석뿐만 아니라 데이터를 시각화하고 예측 모델을 형성하는 등 무척 다양한 업무를 수행할 수 있다고 느꼈다. 따라서 앞으로 프로젝트를 진행하거나 회사 생활을 할 때 핵심 중의 핵심 역량으로 생각이 들었다.
파이썬은 기본적으로 다양한 명령어가 마치 대화하듯 느껴졌다. 따라서 영어나 불어처럼 새로운 언어를 익힌다는 관점에서 접근해야할 것 같다. 즉, 끊임없이 복습하며 우선 친숙해질 예정이다. 그 후 제로베이스의 다양한 프로젝트를 진행하면서 실제로 직접 사용하는 것이 무척 중요할 것으로 보인다.
가장 먼저 진행하는 단계이다. 데이터 읽고, 기본적인 정보들을 확인하고 특정 위치 데이터 파악
Q1. Datra Read하라
import pandas as pd
pandas를 불러오고 앞으로 pd라 부른다
df = pd.read_csv(DriveUrl)
pd.read_csv : 판다스 기능 중 csv파일을 읽고 그 파일은 DriveUrl에 있다
읽어 온 데이터를 데이터 프레임이라는 하나의 객체에 넣겠다
type(df) : 그래서 타입이 뭐냐
Q2. 상위 5개의 행을 출력하시오
df.head()
df의 상위 5개를 볼 수 있다
python은 모든 숫자가 0부터 시작한다
아무것도 없는 칼럼은 색인, 목차인 인덱스이다 (다양한 형태로 설정 가능)
Q3. 데이터의 행과 열의 갯수를 파악하시오
print(df.shape)
데이터프레임 모양을 프린트(출력)하라
전체 행렬 갯수를 알 수 있다
Q4. 전체 칼럼 리스트(꺽새로 나열)를 출력하라
df.columns
Q5. 6번째 칼럼을 출력하라
df.columns[5]
첫번째 숫자가 0이니까
Q6. 6번째 칼럼의 데이터 타입을 확인하라
df.iloc[:,5].dtype
: 은 모든 행을 가져오겠다는 의미
dtype은 데이터 타입이라는 뜻
iloc는 순서, 위치를 기반으로 내가 원하는 데이터에 접근하는 방법
Q7. 데이터셋의 인덱스 구성을 확인하라
df.index
RangeIndex(start=0, stop=51490, step=1)
0번부터 시작 51489번까지 있으며 1씩 증가한다
Q8. 6번째 칼럼의 3번째 값은 무엇인가?
df.iloc[2,5]
Q9. 데이터를 로드하라. 칼럼이 한글이기에 적절한 처리해줘야함
이미 판다스를 불러왔으니 불러올 필요가 없는데 다시 시작하는 경우(런타임이 꺼지면) 불러와야함
df = pd.read_csv(DriveUrl, encoding = 'euc-kr')
encoding은 데이터를 저장할 때 어떠한 형태로 저장했는지에 따라 읽을 때도 동일한 형태로 encoding해줘야 한다
Q10. 데이터 마지막 3개행을 출력하라
df.tail(3)
head ↔ tail
Q11. 수치형 변수를 가진 칼럼을 출력하라
df.select_dtypes(exclude=object).columns
수치형 변수는 numerical 변수 (숫자)
object타입의 파일을 제외하고 exclued는 제외하겠는데, 그 선택한 데이터의 clumns만 보겠다
object는 파이썬 문자열 형태의 데이터
float는 소수점이 있는 데이터, int는 소수점이 없는 데이터
Q12. 범주형 변수를 가진 칼럼을 출력하라
df.select_dtypes(include=object).columns
범주형 변수 = 카테고리별 변수 = 문자열
include는 해당 데이터 형식을 포함하겠다는 뜻
Q13. 각 칼럼의 결측치 숫자를 파악하라
df.isnull().sum()
null값이 있으면 실행이 안되는 코드가 많아서 처리 필요
isnull은 null이 있냐 없냐
sum은 그 값의 합을 파악
Q14. 각 칼럼의 데이터 수, 데이터 타입을 한번에 확인하라
df.info()
RangeIndex: 9621 entries, 0 to 9620 : 총 9621개 데이터가 있고, 인덱스는 0번부터 9620까지 설정되어 있다
Data columns (total 13 columns): 칼럼은 총 13개이다
Non-Null Count : null이지 않은 데이터가 몇 개인가?
dtypes: float64(9), int64(1), object(3) : 실수형 데이터 9개, 정수형 데이터 1개, object type은 3개
memory usage: 977.3+ KB : 이 데이터 용량은 977.3KB이다
Q15. 각 수치형 변수의 분포(사분위, 평균, 표준편차, 최대, 최소)를 확인하라
df.describe()
Q16. 거주인구 칼럼의 값들을 출력하라
df['거주인구']
특정 칼럼 셀력션하는 iloc보다 이것을 더 많이 사용
Q17. 평균 속도 칼럼의 4분위 범위(IQR) 값을 확인하라
df['평균 속도'].quantile(0.75) - df['평균 속도'].quantile(0.25)
75% 위치 - 25% 위치
Q18. 읍면동명 칼럼의 유일값 갯수를 출력하라
df['읍면동명'].nunique()
Q19. 읍면동명 칼럼의 유일값을 모두 출력하라
df['읍면동명'].unique()
필터링 : 원하는 데이터를 필터링 해서 보겠다
Sorting : 기준을 갖고 정렬
Q21. quantity 칼럼 값이 3인 데이터를 추출하여 첫 5행을 출력하라
df[df['quantity']==3].head()
df의 어떤 값을 가져올건데 그 값은 안쪽의 값
그 값은 quantity가 3인 데이터 전체를 가져오겠다
== 두개 있어야 한다. (하나 있으면 오류 발생)
해당 형태는 index가 꼬여있다고 말한다
Q22. quantity 칼럼 값이 3인 데이터를 추출하여 index를 0부터 정렬하고 첫 5행을 출력하라
df.loc[df['quantity']==3].head().reset_index(drop=True)
reset_index : 인덱스를 리셋하겠다
drop=True : 기존 인덱스를 굳이 데이터로 만들 필요가 없으니 drop, 즉 없앤다.
Q23. quantity, item_price 두개의 칼럼으로 구성된 새로운 데이터 프레임을 정의하라
df2 = df[['quantity','item_price']]
df[['quantity','item_price']] 만 해도 두개의 칼럼으로 구성된 모든 행 볼 수 있다
새로운 데이터로 정의하기 위해 df2(새로운 데이터 프레임 이름) = 을 추가함
Q24. item_price 칼럼의 달러표시 문자를 제거하고 float 타입으로 저장하여 new_price 칼럼에 저장하라
df['new_price'] = df['item_price'].str[1:].astype('float')
item_price 값을 실수 형태의 타입으로 선언하고 사칙연산을 수행하기 위한 데이터 전처리 작업이다
df['new_price'] = 는 new price라는 데이터 프레임을 정의
데이터 프레임에 넣을 값은 우항
df['item_price'].str[1:]은 item_price 문자 열의 두번째 글자부터 가져오겠다는 뜻, 왜냐하면 0은 현재 $표시니까
하지만 아직 문자열 표시임
astype('float')은 float형식으로 타입을 바꾸겠다는 뜻
Q25. new_price 칼럼이 5이하의 값을 가지는 데이터프레임을 추출하고, 전체 갯수를 구하여라
len(df[df['new_price'] <=5])
df[df['new_price'] <=5]는 5이하 가져오는 뜻
len은 갯수를 세는 명령어
Q26. item_name명이 Chicken Salad Bowl인 데이터 프레임을 추출하고 index 값을 초기화 하여라
df.loc[df.item_name =='Chicken Salad Bowl'].reset_index(drop=True)
[’칼럼’] 방식으로 불러와도 되고 df.칼럼명으로 해도 된다. (다만 이 방법은 칼럼명에 띄어쓰기 등 공백이 있어서는 안된다)
loc를 빼도 진행된다
loc는 값 기준으로 데이터 인덱싱 (iloc는 순서 위치 기반)
Q27. new_price값이 9이하이고 item_name값이 Chicken Salad Bowl인 데이터 프레임을 추출하라
Ans = df.loc[(df.item_name =='Chicken Salad Bowl') & (df.new_price <= 9)]
조건은 대괄호 안에 넣고 2가지 이상 조건은 각각 소괄호로 독립적으로 묶어주고
모두 만족해야하니 &로 묶어준다
Ans라는 이름의 객체에 할당
Ans.head()
Q28. df의 new_price 칼럼 값에 따라 오름차순으로 정의하고 index를 초기화 하여라
Ans = df.sort_values('new_price').reset_index(drop=True)
sort_values(’ sorting 기준 칼럼값’, 차순)
오름차순이 디폴트임
Q29. df의 item_name 컬럼 값중 Chips 포함하는 경우의 데이터를 출력하라
Ans = df.loc[df.item_name.str.contains('Chips')]
str.contains(’단어’)를 통해 특정 칼럼의 키워드 값을 포함하는 데이터 추출
Q30. df의 짝수번째 칼럼만을 포함하는 데이터프레임을 출력하라
Ans = df.iloc[:,::2]
::2라고하면 짝수 전체를 의미
Q31. df의 new_price 칼럼 값에 따라 내림차순으로 정리하고 index를 초기화 하여라
Ans = df.sort_values('new_price',ascending=False).reset_index(drop=True)
ascending=False은 내림차순 기준으로 정렬
Q32. df의 item_name 컬럼 값이 Steak Salad 또는 Bowl 인 데이터를 인덱싱하라
Ans = df.loc[(df.item_name =='Steak Salad') | (df.item_name =='Bowl')]
인덱싱하라 = 찾아라
또는은 | 을 사용한다 (원 표시 + 쉬프트)
Q33. df의 item_name 컬럼 값이 Steak Salad 또는 Bowl 인 데이터를 데이터 프레임화 한 후, item_name를 기준으로 중복행이 있으면 제거하되 첫번째 케이스만 남겨라
Ans = df.loc[(df.item_name =='Steak Salad') | (df.item_name =='Bowl')]
Ans = Ans.drop_duplicates('item_name')
drop_duplicates는 분석해야하는 데이터가 있을 때 중복되는 데이터를 없앨 때 주로 사용 (모든 칼럼값 동일 데이터)
여기선 실습이라 달라도 활용해본 것
Q34. df의 item_name 컬럼 값이 Steak Salad 또는 Bowl 인 데이터를 데이터 프레임화 한 후, item_name를 기준으로 중복행이 있으면 제거하되 마지막 케이스만 남겨라
Ans = Ans.drop_duplicates('item_name',keep='last')
keep=을 통해 첫 or 마지막 결정
Q35. df의 데이터 중 new_price값이 new_price값의 평균값 이상을 가지는 데이터들을 인덱싱하라
Ans = df.loc[df.new_price >= df.new_price.mean()]
평균값이 궁금하면 df.new_price.mean()
Q36. df의 데이터 중 item_name의 값이 Izze 데이터를 Fizzy Lizzy로 수정하라
df.loc[df.item_name =='Izze','item_name'] = 'Fizzy Lizzy’
loc은 값에 접근할 때 자주 사용한다
단일 조건을 선택할 땐 loc를 안 써도 되지만 행과 열에 대해 독립적으로 sorting하거나 filtering할 땐 무조건 loc를 사용해야 한다
[]은 lzze인 칼럼을 가져오고 fizzy lizzy로 대체하라는 뜻
Q37. df의 데이터 중 choice_description 값이 NaN 인 데이터의 갯수를 구하여라
Ans = df.choice_description.isnull().sum()
하나의 칼럼에 대해서만 출력하니 df.칼럼명
Q38. df의 데이터 중 choice_description 값이 NaN 인 데이터를 NoData 값으로 대체하라(loc 이용)
df.loc[df.choice_description.isnull(),'choice_description'] ='NoData’
Q39. df의 데이터 중 choice_description 값에 Black이 들어가는 경우를 인덱싱하라
Ans = df[df.choice_description.str.contains('Black')]
여기선 조건이 하나니 loc를 안써도 된다
만약 list(Ans['choice_description'])[1]
choice_description을 리스트로 두고 첫번째에만 접근해서 풀네임 파악할 수 있음
Q40. df의 데이터 중 choice_description 값에 Vegetables 들어가지 않는 경우의 갯수를 출력하라
Ans = len(df.loc[~df.choice_description.str.contains('Vegetables')])
~표시를 앞에 넣어주면 not이라는 의미이다
Q41. df의 데이터 중 item_name 값이 N으로 시작하는 데이터를 모두 추출하라
Ans = df[df.item_name.str.startswith('N')]
str.startswith(’시작단어’)
Q42. df의 데이터 중 item_name 값의 단어갯수가 15개 이상인 데이터를 인덱싱하라
Ans = df[df.item_name.str.len() >=15]
str.len()는 단어 갯수를 세준다 (공백 포함)
Q43. df의 데이터 중 new_price값이 lst에 해당하는 경우의 데이터 프레임을 구하고 그 갯수를 출력하라 lst =[1.69, 2.39, 3.39, 4.45, 9.25, 10.98, 11.75, 16.98]
lst =[1.69, 2.39, 3.39, 4.45, 9.25, 10.98, 11.75, 16.98]
lst 정의
Ans = df.loc[df.new_price.isin(lst)]
isin은 (리스트 형태 데이터) 하면 그 여러 조건들에 해당하는 데이터를 한번에 찾아주는 문법
display(Ans.head(3))은 표 형식으로 출력해주는 것
print(len(Ans)) 와 함께 쓰니 한 줄로도 출력
그룹을 지어 특정 관점, 기준으로 데이터를 보는 의미
Q45. 데이터의 각 host_name의 빈도수를 구하고 host_name으로 정렬하여 상위 5개를 출력하라
host_name으로 grouping해야함
2가지 방법 존재
Ans = df.groupby('host_name').size().sort_index()
첫번째 방법
(’그룹명’)으로 groupby(묶어서)
size는 null값이 있어도 센다 (count는 null값은 세지 않는다)
앞에 있는 ‘host_name’(grouping 선언한 것)가 인덱스로 선언된다
sort_index는 인덱스 설정된 것을 알파벳, 가나다 순으로 sorting
Ans = df.host_name.value_counts().sort_index()
두번째 방법
value_counts는 상당히 많이 사용하는 문법유니크한 갯수를 세주고 내림차순으로 정렬해준다
null값까지 세고 싶으면 value_counts(dropna=False)로 쓰면 된다
Q46. 데이터의 각 host_name의 빈도수를 구하고 빈도수로 정렬하여 상위 5개를 출력하라
df.host_name.value_counts().to_frame().head()
기본 문법
이미 value_counts가 내림차순이라 칼러명빼고 동일한 데이터 프레임 표시됨
Ans = df.groupby('host_name').size().\
to_frame().rename(columns={0:'counts'}).\
sort_values('counts',ascending=False)달러 표시를 사용하면 엔터로 기능
to_frame이라는 뜻은 데이터프레임화 하겠다는 의미
rename(columns={0:'counts'}은 0이라는 칼럼명을 counts로 변경한다는 뜻
sort_values('counts',ascending=False)는 counts를 기준으로 내림차순으로 정렬하겠다는 의미
Q47. neighbourhood_group의 값에 따른 neighbourhood컬럼 값의 갯수를 구하여라
Ans = df.groupby(['neighbourhood_group','neighbourhood'], as_index=False).size()
groupby를 대괄호로 묶어주면 여러 기준으로 묶어줄 수 있다
size로 세거나 그 전에 null값 데이터 전처리해서 count로 세기
as_index=False를 빼면 데이터프레임이 아닌 시리즈로 표시된다as_index=False는 인덱스로 설정된 neighborurhood_group과 neighborhood를 인덱스로 인식하지 않고 하나의 칼럼으로 설정해달라는 옵션
Q48. neighbourhood_group의 값에 따른 neighbourhood컬럼 값 중 neighbourhood_group그룹의 최댓값들을 출력하라
Ans= df.groupby(['neighbourhood_group','neighbourhood'], as_index=False).size()\
.groupby(['neighbourhood_group'], as_index=False).max()
첫번째 줄을 통해 size 즉, 빈도 수 확인하고
두번째 줄 덕분에 neighborhood_group별로 groupby하고 max 파악
두번째 줄 빼면 neighborhood_group이 동일한 행 독립적으로 존재
Q49. neighbourhood_group 값에 따른 price값의 평균, 분산, 최대, 최소 값을 구하여라
Ans = df.groupby('neighbourhood_group')['price'].agg(['mean','var','max','min'])
이전에는 빈도수만 보았기에 size
이제는 특정 칼럼을 활용해 사칙연산을 진행해야 하기 때문에 칼럼을 하나 더 선언
df.groupby('neighbourhood_group')neighbourhood_group으로 데이터를 묶고
['price']
price 칼럼 데이터를 볼건데
agg(['mean','var','max','min'])
여기에 어떤 사칙연산을 할 것인지 말함
agg는 aggregate function 즉, 어떤 사칙연산을 할 것인지 선언하는 것
대괄호로 묶으면 여러 사칙연산 가능
Q51. neighbourhood 값과 neighbourhood_group 값에 따른 price 의 평균을 구하라
Ans = df.groupby(['neighbourhood','neighbourhood_group']).price.mean()
49번 문제처럼 칼럼명을 대괄호 따음표로 묶어도 되고 점 표시로 해도 된다
하나의 사칙연산을 할 땐 agg안써도 된다
만약 Ans = df.groupby(['neighbourhood','neighbourhood_group']. as_index=False).price.mean()
라고 하면 시리즈가 아닌 데이터프레임 형태로 표시
Q52. neighbourhood 값과 neighbourhood_group 값에 따른 price 의 평균을 계층적 indexing 없이 구하라
계층적 인덱스가 시리즈를 의미한다
Ans = df.groupby(['neighbourhood_group', 'neighbourhood']).price.mean().unstack()
unstack을 사용해서 neighbourhood_group의 모든 데이터를 첫번째 열로 피벗해서 표시 (행 이름들)
neighbourhood는 열 이름들로 배정
둘 순서 바꾸면 행 열 위치 바뀜
Q53. neighbourhood 값과 neighbourhood_group 값에 따른 price 의 평균을 계층적 indexing 없이 구하고 nan 값은 -999값으로 채워라
Ans = df.groupby(['neighbourhood','neighbourhood_group']).price.mean().unstack().fillna(-999)
fillna는 빈값이 있으면 어떤 걸로 채울지 설정
Q54. 데이터중 neighbourhood_group 값이 Queens값을 가지는 데이터들 중 neighbourhood 그룹별로 price값의 평균, 분산, 최대, 최소값을 구하라
Ans = df[df.neighbourhood_group=='Queens'].groupby(['neighbourhood']).price.agg(['mean','var','max','min'])
df[df.neighbourhood_group=='Queens']
df의 neighbourhood_group이 queens인 데이터를 모두 가져온다
groupby(['neighbourhood'])
위에서 구한 데이터를 neighbourhood로 묶는다
price.agg(['mean','var','max','min'])
price값의 사칙연산들을 보겠다
Q55. 데이터중 neighbourhood_group 값에 따른 room_type 컬럼의 숫자를 구하고 neighbourhood_group 값을 기준으로 각 값의 비율을 구하여라
Ans = df[['neighbourhood_group','room_type']].groupby(['neighbourhood_group','room_type']).size().unstack()
df[['neighbourhood_group','room_type']]
대괄호 두개로 묶어서 특정 칼럼에 대한 데이터만 가져옴
groupby(['neighbourhood_group','room_type']).size().unstack()
가져온 데이터에 대해 해당 기준에 따라 groupby하고 숫자 세고 unstack을 한다
여기까지하면 neighbourhood_group을 행, room_type을 열로 갖는 빈도수를 구한다
Ans.loc[:,:] = (Ans.values /Ans.sum(axis=1).values.reshape(-1,1))
Ans.loc[:,:]
loc는 행열을 어떤 기준으로 값을 가져온다는 의미이고 :은 모든 값을 가져온다는 의미
Ans.sum(axis=1)
axis는 칼럼값을 기준으로 sum을 하겠다는 의미 (각 행에 있는 데이터 총 sum값을 구함)
Ans.values
각 값에 대한 array로 뽑아준다 (matrix형태로 뽑아주는 것)
Ans.sum(axis=1).values.reshape(-1,1))까지가 한 묶음으로 이 값으로 Ans.values을 나눈 것
사칙연산할 때 배열끼리 차원의 갯수와 형태를 맞춰줘야하기 때문에
values는 하나의 array만 나오니까
values.reshape(-1,1))
values는 값만 뽑아오는 명령어
reshape은 행과 열의 차원을 변경
Q56. 데이터를 로드하고 데이터 행과 열의 갯수를 출력하라
Ans = df.shape
df.shape 명령어를 통해 갖고 있는 데이터의 행과 열을 알 수 있다
Q57. Income_Category의 카테고리를 map 함수를 이용하여 다음과 같이 변경하여 newIncome 컬럼에 매핑하라
dic = {
'Unknown' : 'N',
'Less than $40K' : 'a',
'$40K - $60K' : 'b',
'$60K - $80K' : 'c',
'$80K - $120K' : 'd',
'$120K +' : 'e'
}
dic은 사전이어서 보통 한 쌍의 데이터로 이뤄져 있다
unknow이 n으로, less than부터 $40K는 a로 (이하 생략) 참조할 수 있는 매핑 파일을 만드는 것
df['newIncome'] = df.Income_Category.map(lambda x: dic[x])
newincome이라는 새로운 데이터 정의
df.Income_Categorydf의 income_category를
map(lambda x: dic[x])
x는 사용자 정의함수이므로 여기서는 바로 앞 변수인 Income_Category를 의미한다
lambda는 익명 함수를 생성하는데 사용되는 키워드
def와 달리 이름이 없고, 함수를 짧게 만들어 줌
lambda 매개변수: 표현식
람다 x를 앞에 정의한 dic[x]에 넣어주겠다는 의미
income_category가 매핑된다
Ans = df[['newIncome', 'Income_Category']]
newincome만 넣으면 칼럼명 newincome에 n~e로 정의 된 값이 표시됨
Q58. Income_Category의 카테고리를 apply 함수를 이용하여 다음과 같이 변경하여 newIncome 컬럼에 매핑하라
57번 문제와 동일하다
map(lambda)로 풀 수도 있고 apply를 사용할 수도 있다
dic 정의할 땐 보통 map 사용
apply는 사용자 정의 함수를 데이터 프레임에 적용할 때 많이 사용한다
def changeCategory(x):
if x =='Unknown':
return 'N'
elif x =='Less than $40K':
return 'a'
elif x =='$40K - $60K':
return 'b'
elif x =='$60K - $80K':
return 'c'
elif x =='$80K - $120K':
return 'd'
elif x =='$120K +' :
return 'e'
def는 definition의 약자
파이썬은 보통 다양한 패키지를 불러와서 그 속에 포함된 함수를 사용한다
def는 내가 함수를 정의할 때 사용
def 함수 이름(함수 인자)
인자는 다수일 수 있다
elif는 else if의 준말
df['newIncome'] =df.Income_Category.apply(changeCategory)
Ans = df[['newIncome', 'Income_Category']]
Q59. Customer_Age의 값을 이용하여 나이 구간을 AgeState 컬럼으로 정의하라. (0-9: 0 , 10-19: 10 , 20-29: 20) … 각 구간의 빈도수를 출력하라
df['AgeState'] = df.Customer_Age.map(lambda x: x//10 *10)
//는 나눗셈의 몫을 의미한다. 즉 //*을 통해 몫을 구한 후 10을 곱한 것
구한 값을 customer age에 매핑해서 agestate에 넣는다
Ans = df['AgeState'].value_counts().sort_index()
value_counts() 즉, agestate의 가장 빈도 수가 많은 값 순으로 배열
Q60. Education_Level의 값중 Graduate단어가 포함되는 값은 1 그렇지 않은 경우에는 0으로 변경하여 newEduLevel 컬럼을 정의하고 빈도수를 출력하라
두가지 방법 존재 (map과 numpy의 np.where)
df['newEduLevel'] = df.Education_Level.map(lambda x : 1 if 'Graduate' in x else 0)
df['newEduLevel'] = newEduLevel 라는 칼럼을 하나 정의할 것
df.Education_Level 정의할 값은 df의 education_level입니다
map(lambda x : 1 if 'Graduate' in x else 0)거기에 매핑할 건데
if else의 축약문으로 생각하면 된다
x(education_level) 안에 graduate가 있으면 1로, 그렇지 않으면 0
map대신 apply 써도 동일한 값 나옴
Ans = df['newEduLevel'].value_counts()
groupby랑 size를 사용해서 빈도수를 구할 수도 있음
import numpy as np
df['newEduLevel'] = np.where( df.Education_Level.str.contains('Graduate'), 1, 0)
Ans = df['newEduLevel'].value_counts()
Ans
두번째 방법 (numpy 패키지)
np.where은 앞 조건 만족하면 어떤 값 아니면 다른 값을 변환해라는 문법
np.where(조건, 어떤 값, 다른 값)
Q62. Marital_Status 컬럼값이 Married 이고 Card_Category 컬럼의 값이 Platinum인 경우 1 그외의 경우에는 모두 0으로 하는 newState컬럼을 정의하라. newState의 각 값들의 빈도수를 출력하라
def check(x):
if x.Marital_Status =='Married' and x.Card_Category =='Platinum':
return 1
else:
return 0
사용자 정의 함수
x가 marital_status가 married이고 card_category가 platinum이면 1 아니면 0 변환
df['newState'] = df.apply(check,axis=1)
apply앞에 칼럼명 없는 이유
조건을 건 데이터는 married와 platinum이기 때문에 하나의 칼럼을 x로 선언할 수가 없다 (martial_status뿐만 아니라 card_category 칼럼도 봐야하니까)
그래서 데이터프레임 전체에 apply하는 것
axis=1
그럴 때 해당 함수의 기준을 정해줘야하는데 열기준으로 수행한다고 선언
Ans = df['newState'].value_counts()
Q63. Gender 컬럼값 M인 경우 male F인 경우 female로 값을 변경하여 Gender 컬럼에 새롭게 정의하라. 각 value의 빈도를 출력하라
def changeGender(x):
if x =='M':
return 'male'
else:
return 'female'
df['Gender'] = df.Gender.apply(changeGender)
Ans = df['Gender'].value_counts()
각 행은 female과 male로 표시 됨
Time_Series는 보통 시계열 데이터이다
데이터 타입은 수치형 데이터(numerical data)와 문자열 데이터, 시계열 데이터가 있다
Q65. Yr_Mo_Dy을 판다스에서 인식할 수 있는 datetime64타입으로 변경하라
df.Yr_Mo_Dy = pd.to_datetime(df.Yr_Mo_Dy)
시계열 데이터로 바꾸면 컨트롤하기 쉽게 된다
초기에 시계열 데이터로 데이터 전처리 하는게 좋음
Q66. Yr_Mo_Dy에 존재하는 년도의 유일값을 모두 출력하라
Ans = df.Yr_Mo_Dy.dt.year.unique()
dt.year은 Yr_Mo_Dy가 시계열 데이터로 선언되어서 year만 추출한다
unique()를 통해 유일값 출력
nunique는 유일 숫자값
Q67. Yr_Mo_Dy에 년도가 2061년 이상의 경우에는 모두 잘못된 데이터이다. 해당경우의 값은 100을 빼서 새롭게 날짜를 Yr_Mo_Dy 컬럼에 정의하라
def fix_century(x):
fix_century라는 함수 정의
import datetime
datetime이라는 패키지 불러옴
함수 안에 넣었기에 이 함수를 적용할 때 자동으로 datetime이 실행된다
year = x.year - 100 if x.year >= 2061 else x.year
x.year가 2061이상이면 x.year에서 100을 빼고 아니면 x.year을 그냥 써라
return pd.to_datetime(datetime.date(year, x.month, x.day))
이 함수가 끝났을 때 최종으로 내뱉을거냐
현재 year는 함수를 통해 숫자로 나온다
datetime.date(year, x.month, x.day)year, x.month, x.day를 datetime.date으로 선언
pd.to_datetime(datetime.date(year, x.month, x.day))
datetime.date(year, x.month, x.day)을 다시 datetime(시간 형태 데이터 타입)으로 변경
df['Yr_Mo_Dy'] = df['Yr_Mo_Dy'].apply(fix_century)
이후
Ans = df.head(4)
Ans를 통해 출력해도 되고
df.Yr_Mo_Dy.dt.year.unique()
를 통해 유일값을 파악해도 된다
Q68. 년도별 각컬럼의 평균값을 구하여라
Ans = df.groupby(df.Yr_Mo_Dy.dt.year).mean(numeric_only=True)
df.Yr_Mo_Dy.dt.year
df.Yr_Mo_Dy의 year값 추출
df.groupby
을 grouping
mean
의 평균값을 구하는데
(numeric_only=True)
numeric data에 대해서만 적용
문자열 등은 출력 X
Q69. weekday컬럼을 만들고 요일별로 매핑하라 ( 월요일: 0 ~ 일요일 :6)
df['weekday'] = df.Yr_Mo_Dy.dt.weekday
weekday를 숫자로 변환
Ans = df['weekday'].head(3).to_frame()
data frame으로 변환
Q70. weekday컬럼을 기준으로 주말이면 1 평일이면 0의 값을 가지는 WeekCheck 컬럼을 만들어라
df['WeekCheck'] = df['weekday'].map(lambda x : 1 if x in [5,6] else 0)
x는 앞에 있는 weekday
토요일은 5, 일요일은 6
Ans = df[['weekday', 'WeekCheck']]
weekcheck 열에 출력되는데, 앞에 weekday를 넣어서 0~6 즉 요일값도 보게 표현
Q71. 년도, 일자 상관없이 모든 컬럼의 각 달의 평균을 구하여라
Ans = df.groupby(df.Yr_Mo_Dy.dt.month).mean(numeric_only=True)
Q72. 모든 결측치는 컬럼기준 직전의 값으로 대체하고 첫번째 행에 결측치가 있을경우 뒤에있는 값으로 대체하라
df = df.fillna(method='ffill').fillna(method='bfill')
fillna는 빈값에 어떤 값을 넣겠다는 정의
fillna(-999)처럼 특정값 넣어도 됨
fillna(method=’ffill’)은 직전의 값을 넣겠다는 의미 (bfill은 뒤에 있는 값)
이때 첫 행은 여전히 null인 상태이다
그래서 두번째 fillna를 통해 여전히 null인 값을 변환해준다
df.isnull().sum()
Q73. 년도 - 월을 기준으로 모든 컬럼의 평균값을 구하여라
Ans = df.groupby(df.Yr_Mo_Dy.dt.to_period('M')).mean(numeric_only=True)
평균값 기준이 되는 groupby는 필수
dt.to_period(’M’)은 연도별 월 형태 (ex. 1961-01)
Q74. 년도 - 월을 기준으로 모든 컬럼의 최대값을 구하여라
Ans = df.groupby(df.Yr_Mo_Dy.dt.to_period('M')).max(numeric_only=True)
Q75. RPT와 VAL의 컬럼을 일주일 간격으로 각각 이동평균한값을 구하여라
이동평균한 값은 하나씩 시프트 되면서 이동하면서 평균을 구하는 개념
Ans= df[['RPT','VAL']].rolling(7).mean()
df[['RPT','VAL']]라는 데이터 프레임을 만듦
rolling(7)은 7개 데이터 기준으로즉 rolling(1)은 하나 안하나 동일
mean() 평균값 추출한다
앞 6개 행은 NaN임
Q76. 년-월-일:시 컬럼을 pandas에서 인식할 수 있는 datetime 형태로 변경하라. 서울시의 제공데이터의 경우 0시가 24시로 표현된다
def change_date(x):
import datetimechange_date라는 함수를 만든다
hour = x.split(':')[1]
split은 :기준으로 데이터를 나눈다는 의미
hour라는 x 인자데이터를 : 기준으로 첫번째의 값을 가져오고 (ex. 2021-05-15:15에서 15)
date = x.split(":")[0]
date는 : 기준으로 0번째 데이터를 가져온다 (ex. 2021-05-15:15에서 2021-05-15)
if hour =='24':
hour ='00:00:00'hour가 24시면 00:00:00:00으로
FinalDate = pd.to_datetime(date +" "+hour) + datetime.timedelta(days=1)
hour가 24시면 위에서 가져온 date에 위 if값이 적용된 hour를 붙이고 days에 +1을 해서 datetime 유형으로 변환한 finaldata를 만들겠다
else:
hour = hour +':00:00'
FinalDate = pd.to_datetime(date +" "+hour)그 밖에는 기존값을 사용 하겠다
return FinalDate
두 조건에 만족하는 값을 FinalData로
df['(년-월-일:시)'] = df['(년-월-일:시)'].apply(change_date)
Ans = df
Ans.head()
Q77. 일자별 영어요일 이름을 dayName 컬럼에 저장하라
df['dayName'] =df['(년-월-일:시)'].dt.day_name()
Q78. 요일별 각 PM10등급의 빈도수를 파악하라
Ans1 = df.groupby(['dayName','PM10등급'],as_index=False).size()
요일별, 각 PM10등급별 빈도수 파악
Ans2 = Ans1.pivot(index='dayName',columns='PM10등급',values='size').fillna(0)
행에 dayname을 넣고 열에 pm10등급을 넣고 value에는 size를 넣는다 (값엔 빈도수를 넣는다)
null값엔 0을 넣는다
Q79. 시간이 연속적으로 존재하며 결측치가 없는지 확인하라
check = len(df['(년-월-일:시)'].diff().unique())
df['(년-월-일:시)'].diff()는 바로 앞 값을 다 빼겠다는 의미
즉 한 객체 내에서 열과 열 / 행과 행의 차이를 출력axis에 따라서 행끼리 비교할지, 열 끼리 비교 (axis=0이면 행, 1이면 열)
시간을 차분할 때 첫 값은 nan, 이후 모든 차분값이 동일하면 연속이라 판단
unique를 줘서 유일값 구함
if check ==2:
Ans =True즉 2이면 연속적
else:
Ans = False
3, 4 등 다른 값이면 연속x
Q80. 오전 10시와 오후 10시(22시)의 PM10의 평균값을 각각 구하여라
Ans = df.groupby(df['(년-월-일:시)'].dt.hour).mean(numeric_only=True).iloc[[10,22],[0]]
iloc을 통해 원하는 값인 10시와 22시만 가져옴
Q81. 날짜 컬럼을 index로 만들어라
df.set_index('(년-월-일:시)',inplace=True)
set_index는 인덱스를 어떤 칼럼으로 설정할지 선언
inplace=True 옵션은 반영된 값을 원본데이터에 바로 반영하겠다는 의미
Q83. Indicator을 삭제하고 First Tooltip 컬럼에서 신뢰구간에 해당하는 표현을 지워라
df.drop('Indicator',axis=1,inplace=True)
drop할 때 axis=1 (열 삭제), axis=0 (행 삭제)
df['First Tooltip'] = df['First Tooltip'].map(lambda x: float(x.split("[")[0]))
first tooltip(x)을 split할 건데 대괄호 기준으로 split해서 앞의 숫자만 남기고
float 실수 형태로 변경해서
first tolltip에 넣겠다
Q84. 년도가 2015년 이상, Dim1이 Both sexes인 케이스만 추출하라
target = df[(df.Period >=2015) & (df.Dim1 =='Both sexes')]
and조건이므로 각각 소괄호
Q85. 84번 문제에서 추출한 데이터로 아래와 같이 나라에 따른 년도별 사망률을 데이터 프레임화 하라
Ans = target.pivot(index='Location',columns='Period',values='First Tooltip')
피벗할 때 index, columns, values는 세트
Q86. Dim1에 따른 년도별 사망비율의 평균을 구하라
Ans = df.pivot_table(index='Dim1',columns='Period',values='First Tooltip',aggfunc='mean')
Q87. 데이터에서 한국 KOR 데이터만 추출하라
kr = df[df.Country=='KOR']
확인하는 방법
kr.Country.unique()
Q88. 한국 올림픽 메달리스트 데이터에서 년도에 따른 medal 갯수를 데이터프레임화 하라
Ans = kr.pivot_table(index='Year',columns='Medal',aggfunc='size').fillna(0)
특정 값이 적혀있는 것이 아니라 바로 value값을 못 넣으니 aggfunc을 통해 갯수를 셀 수 있다
Ans[['Gold', 'Silver', 'Bronze']]
열 이름 위치 변경
Q89. 전체 데이터에서 sport종류에 따른 성별수를 구하여라
Ans = df.pivot_table(index='Sport',columns='Gender',aggfunc='size')
value값을 바로 사용할지 aggfunc을 사용할지 유의
데이터 병합, 조인 기능
Q91. df1과 df2 데이터를 하나의 데이터 프레임으로 합쳐라
total = pd.concat([df1,df2], axis=0)
행 기준 : 위 아래로 합친다
열 기준 : 오른쪽에 붙는다 (axis=1)
Q92. df3과 df4 데이터를 하나의 데이터 프레임으로 합쳐라. 둘다 포함하고 있는 년도에 대해서만 고려한다
Ans = pd.concat([df3,df4],join='inner')
.reset_index(drop=True) 을 통해 인덱스 재설정 가능
Q93. df3과 df4 데이터를 하나의 데이터 프레임으로 합쳐라. 모든 컬럼이 출력될 수 있도록 고려하라
Ans = pd.concat([df3,df4],join='outer').fillna(0)
null값 처리 유의
Q94. df5과 df6 데이터를 하나의 데이터 프레임으로 merge함수를 이용하여 합쳐라. Algeria컬럼을 key로 하고 두 데이터 모두 포함하는 데이터만 출력하라
Ans = pd.merge(df5,df6,on='Algeria',how='inner')
merge는 join의 개념이다
on=algeria 키 값으로 붙일거다
inner라 df5가 기준이고 algeria가 있을 때 열 추가 됨
(merge는 A라는 데이터에 추가 데이터를 가져올 때 많이 사용, join의 개념)
(concat은 위아래 옆 등 합치는 개념)
Q95. df5과 df6 데이터를 하나의 데이터 프레임으로 merge함수를 이용하여 합쳐라. Algeria컬럼을 key로 하고 합집합으로 합쳐라
Ans =pd.merge(df5,df6,on='Algeria',how='outer').fillna(0)
Q97. 'Unnamed: 0' and 'Id'를 제거하라
del df['Unnamed: 0']
del df['Id']
한번 삭제한 데이터를 리드할 수 없다
del보다 df2를 새로 만드는 것 추천 (원본 데이터 보존)
df2 = df[['Name', 'Year', 'Gender', 'State', 'Count']]
Q98. 데이터셋에 남성 이름이 더 많나요, 아니면 여성 이름이 더 많나요?
df['Gender'].value_counts()
Q99. 데이터셋을 이름별로 그룹화여 'Count'를 Sum하고, names라는 변수에 할당하세요. (상위 5개의 행만 출력)
names = pd.DataFrame(df.groupby('Name')['Count'].sum())
['Count'].sum()이 그룹된 name에 값으로 들어가진다
pd.DataFrame을 통해 데이터프레임화
names.sort_values(by=['Count'], ascending=0).head(5)
by없어도 되지만 다중 sorting할 때는 by 넣어줘야 한다
ascending=0 내림차순(False)
ascending=1 오름차순(True)
Q100. 서로 다른 이름은 총 몇개인가요?
df['Name'].nunique()
Q100. 가장 많이 등장한 이름은?
names[names.Count == names.Count.max()]
names.count에서 가장 많은 값의 names(맨 앞)을 출력해줘
Q101. 가장 적게 등장한 이름은 몇개인가요?
len(names[names.Count == names.Count.min()])
len을 빼면 가장 적게 등장한 이름 복수개가 등장한다
Q102. 중앙값(median)의 개수를 가지고 있는 이름은?
names[names.Count == names.Count.median()]
Q103. 이름 개수(Count)의 표준편차를 구하시오
names.Count.std()
Q104. names의 평균, 최소, 최대, 표준편차, 4분위수를 계산하시오
names.describe()
DataFrame
2차원의 엑셀 데이터형태의 판다스 데이터 타입
Series
데이터 프레임에서 하나의 칼럼
Q105. 상위 데이터 셋의 정보를 활용하여 데이터 프레임을 생성하시오
import pandas as pd
df = pd.DataFrame({"name": ['Bulbasaur', 'Charmander','Squirtle','Caterpie'],
"evolution": ['Ivysaur','Charmeleon','Wartortle','Metapod'],
"type": ['grass', 'fire', 'water', 'bug'],
"hp": [45, 39, 44, 45],
"pokedex": ['yes', 'no','yes','no']})
중괄호 주의
Q106. 컬럼의 순서를 name, type, hp, evolution, pokedex로 변경하시오
df = df[['name', 'type', 'hp', 'evolution','pokedex']]
Q107. 새로운 컬럼을 생성하고 임의의 값을 할당하시오
df['place'] = ['sea','mountain','lake','forest']
기존에 없는 칼럼명을 넣어야 한다
리스트 형태로 넣어야 한다
Q108. 각 컬럼에 대한 타입을 확인하시오
두 가지 방법
df.info()
첫번째 방법
훨씬 많은 정보 제공
df.dtypes
타입만 제공해준다
Q109. hp가 40이상인 데이터를 출력하시오
df[df['hp'] >= 40]
대괄호 안에 원하는 조건 삽입
Q109-2. 전체 데이터 셋 중에서 name과 type만 출력하시오
df[['name', 'type']]
Q110. 데이터 세트에 인덱스를 one, two, three, four로 변경하시오. (새로운 객체에 할당 할 것)
df2 = df.copy()
df2 = df만 하면 충돌 발생 가능성 (동조)
copy 사용 권장
df2.index = ['one', 'two', 'three', 'four']
Q111. name을 인덱스로 설정하시오
df2.set_index('name', inplace=True)
inplace=True를 해야 실제 데이터에 반영
Q112. 데이터 세트를 csv파일로 저장하시오
df2.to_csv('sample.csv’)
(내가원하는데이터프레임).to_csv(원하는 파일 이름.csv)
저장 위치import os
os.getcwd() 하면 경로 파악
os.chdir('특정경로') 하면 경로 변경
Q113. 아래와 같이 새로운 데이터 프레임을 생성하고, 기존 데이터 프레임과 병합하시오
Ans = pd.concat([df, new_df], axis=0).reset_index(drop=True)
Q113. Ans에서 place 1번째와 3번째 row에 NaN값을 입력하시오
import numpy as np
Ans.loc[[0,2],'place'] = np.nan
loc[[행,열], 칼럼]
loc는 값에 접근하는 방식
np.nan은 Null값 선언
시각화에 자주 사용되는 패키지
import matplotlib.pyplot as plt
import seaborn as sns
colab외 다른 곳에서 사용 시
%matplotlib inline
print the graphs in the notebook (창에 시각화)
시각적 테마 스타일 지정
sns.set_style("white")
Q115. total_bill에 대해서 히스토그램을 그리시오
ttbill = sns.histplot(df.total_bill);
sns시각화 패키지 중 하나인 histplot
단위(bins) 지정없으면 자동 지정
이것만해도 그래프는 그려진다
ttbill.set(xlabel = 'Value', ylabel = 'Frequency', title = "Total Bill");
추가 정보 세팅
xlabel (X축 명칭), ylabel (Y축 명칭), title (히스토그램명)
Q116. total_bill과 tip에 대해서 jointplot을 그리시오
sns.jointplot(x ="total_bill", y ="tip", data = df);
산점도와 히스토그램 한번에 확인
tip에 대한 히스토그램 (우측)
total_bill에 대한 히스토그램 (상단)
Q117. 모든 연속성 변수에 대해서 pairplot을 그리시오
sns.pairplot(df);
산점도 전체 생성 (숫자형 연속형 변수만)
대각선만 히스토그램 (자기 자신에 대해서니까)
Q118. day에 따라 total_bill의 관계를 파악하기 위한 stripplot을 그리시오
sns.stripplot(x = "day", y = "total_bill", data = df);
연속형 변수(total_bill)를 범주형 변수(day)에 따라 어떻게 분포되어 있는지 확인하는 방식
Q119. day와 성별에 따라 tip의 관계를 파악하기 위한 stripplot을 그리시오 ( x축 - tip, y축 - day)
sns.stripplot(x = "tip", y = "day", hue = "sex", data = df);
day와 성별 두 가지 범주형(categorical) 변수를 설정할 때는 한 차원을 더 추가해야 한다 (hue)
Q120. day와 time에 따라 total_bill의 관계를 파악하기 위한 boxplot을 그리시오 ( x축 - day, y축 - total_bill)
sns.boxplot(x = "day", y = "total_bill", hue = "time", data = df);
선을 넘은 점은 outlier로 지칭
박스 안 선은 평균 선이 아닌 중앙값(median)
박스 최하단이 Q1, 최상단이 Q3
선은 1.5*IQR빼거나 합친 값
Q121. 저녁(Dinner)과 점심(Lunch)을 기준으로 한 팁 값에 대해 두 개의 히스토그램을 생성하세요.
sns.set(style = "ticks")
ticks는 y축의 선 표시 옵션
plt.grid(True)
x축 grid 옵션
g = sns.FacetGrid(df, col = "time")
데이터를 넣어주고 칼럼은 time
칼럼은 시간이니 그리드는 시간(디너와 런치)으로 나눠지고
그리고자 하는 것을 아래에 작성
g.map(plt.hist, "tip");
히스토그램을 그리고 tip을 기준으로 mapping하겠다
Q121-2. 남성과 여성을 대상으로 한 두 개의 산점도 그래프를 생성하세요. 이 그래프들은 전체 청구 금액(total_bill)과 팁(tip) 간의 관계를 보여주며, 흡연자와 비흡연자로 구분되어야 합니다.
g = sns.FacetGrid(df, col = "sex", hue = "smoker")
col과 hue 순서가 바뀌어도 괜찮다
g.map(plt.scatter, "total_bill", "tip", alpha =.7)
alpha는 투명도
sns.platter도 가능 (시각적으로 다르지만 기능은 동일)
g.add_legend();
Q123. 남성과 여성의 비율을 나타내는 파이 차트를 생성하세요.
males = (df['Sex'] == 'male').sum()
females = (df['Sex'] == 'female').sum()
proportions = [males, females]
남성 수, 여성 수, 숫자로 표시
파이 차트 만들 때 숫자를 넣어 표현
plt.pie(
proportions,
labels = ['Males', 'Females'],
shadow = False,
colors = ['blue','red'],
explode = (0.15 , 0),
startangle = 90,
autopct = '%1.1f%%’)
plt.axis('equal')
plt.title("Sex Proportion")
plt.tight_layout()
plt.show()
propotions 표현할 건데 labels은 males랑 females로 표시
나머지는 옵션 (그림자, 색, 확장성, 각도, 소수점, 축 기준, 제목, 공백 여백 정도)
Q124. 지불한 요금(Fare)과 나이(Age)를 나타내는 산점도를 생성하세요. 그래프의 색상은 성별에 따라 달라져야 합니다.
lm = sns.lmplot(x = 'Age', y = 'Fare', data = df, hue = 'Sex', fit_reg=False)
fit_reg는 획일선 유무
안넣으면 scatterplot과 유사
lm.set(title = 'Fare x Age')
axes = lm.axes
axes[0,0].set_ylim(-5,)
axes[0,0].set_xlim(-5,85)
x축과 y축의 범위
Q125. 지불한 요금(Fare)에 대한 히스토그램을 생성하세요
import numpy as np
df2 = df.Fare.sort_values(ascending = False)
내림차순
binsVal = np.arange(0,600,10)
600이 아닌 590까지 센다 (최소, 최대, 빈도)
binsVal
plt.xlabel('Fare')
plt.ylabel('Frequency')
plt.title('Fare Payed Histrogram')
plt.show()
Q126. Column명을 아래와 같이 변경하세요.
df.columns = ['sepal_length','sepal_width', 'petal_length', 'petal_width', 'class']
df.columns 단독 사용시 칼럼명 확인
Q127. Column별 NA값이 존재하는지 확인하세요.
df.isnull().sum()
Q127. 'petal_length'의 10번째부터 29번째 행의 값을 NaN으로 변환하세요.
df.iloc[9:29,2] = np.nan
2는 두번째 컬럼인 petal_length를 뜻함 (맨 앞 컬럼은 인덱스)
df.head(30)
Q128. Nan값을 다시 1로 채워 넣으세요.
df.petal_length.fillna(1, inplace = True)
print(df.petal_length.isnull().sum())
다른 방법
Q130.3개의 행에 대해서 모두 Nan값으로 변경하세요
df.iloc[0:3 ,:] = np.nan
:은 모두 선택
Q131.NaN을 가지고 있는 행을 삭제하시오
df = df.dropna(how='any')
any는 모든 칼럼에 하나라도 있으면 삭제한다는 뜻
Q132.index를 다시 0부터 시작할 수 있도록 수정하세요.
df = df.reset_index(drop = True)
Q1. 인기동영상 제작횟수가 많은 채널 상위 10개명을 출력하라 (날짜기준, 중복포함)
df.isnull().sum()
value_couts 전에 null 값 먼저 확인 (null 안세니까)
df.channelTitle.value_counts().head(10)
채널타이틀 기준으로 수를 세어서 출력
Q2. 논란으로 인기동영상이 된 케이스를 확인하고 싶다. dislikes수가 like 수보다 높은 동영상을 제작한 채널을 모두 출력하라
df[df['likes'] < df['dislikes']]['channelTitle'].unique()
Q3. 채널명을 바꾼 케이스가 있는지 확인하고 싶다. channelId의 경우 고유값이므로 이를 통해 채널명을 한번이라도 바꾼 채널의 갯수를 구하여라
change = df[['channelTitle','channelId']].drop_duplicates().channelId.value_counts()
채널타이틀과 채널아이디만있는 df를 가져와서
drop_duplicates를 통해 중복 제거
channelId 기준으로 수를 센다
channelid 기준으로 channeltitle이 여러개면 중복이 있을 수 있다 (이름을 바꾼 경우가 된다)
target = change[change>1]
채널명 변경 케이스
print(len(target))
객체 숫자를 세자
df[df[’channelid’] == [’채널아이디 하나’][’channeltitle’. ‘channelid’]].drop_duplicates() 입력 시 해당 채널 변경 이력 파악 가능
Q4.일요일에 인기있었던 영상들중 가장많은 영상 종류(categoryId)는 무엇인가?
df['trending_date2'] = pd.to_datetime(df['trending_date2'])
시계열 데이터 변경
answer =df.loc[df['trending_date2'].dt.day_name() =='Sunday'].categoryId.value_counts().index[0]
dt.day_name()==’sunday’를 통해 sunday로 찾아볼 수 있음
.categoryId.value_counts().index[0]categoryid 기준으로 수를 세면 그 중 가장 첫번째 인덱스 값을 가져온다는 뜻
print(answer)
Q5.각 요일별 인기 영상들의 categoryId는 각각 몇개 씩인지 하나의 데이터 프레임으로 표현하라
group = df.groupby([df['trending_date2'].dt.day_name(),'categoryId'],as_index=False).size()
df['trending_date2']의 dt.day_name()과 categoryId 기준으로 grouping
size 수를 세고
answer= group.pivot(index='categoryId',columns='trending_date2')
피벗해주는데 value값 지정안해도 size로 자동 지정
display(answer)
print로 해도 출력되지만 display를 통해 데이터 프레임 형태로 출력
Q6. 댓글의 수로 (comment_count) 영상 반응에 대한 판단을 할 수 있다. viewcount대비 댓글수가 가장 높은 영상을 확인하라 (view_count값이 0인 경우는 제외한다)
target2= df.loc[df.view_count!=0]
view_count가 0이 아닌 조건 만족
t = target2.copy()
target2 원본 유지
t['ratio'] = (target2['comment_count']/target2['view_count']).dropna()
뷰 카운트 대비 코멘트 카운트를 구하고 null값 오류 방지차 dropna
result = t.sort_values(by='ratio', ascending=False).iloc[0].title
내림차순으로 정렬하고 첫번째 값의 타이틀에 대한 값만 가져올 것이다
Q7. 댓글의 수로 (comment_count) 영상 반응에 대한 판단을 할 수 있다.viewcount대비 댓글수가 가장 낮은 영상을 확인하라 (view_counts, ratio값이 0인경우는 제외한다.)
ratio = (df['comment_count'] / df['view_count']).dropna().sort_values()
ratio[ratio!=0].index[0]
없어도 됨
result= df.iloc[ratio[ratio!=0].index[0]].title
ratio가 0값이 아닌 첫번째 인덱스의 타이틀만 가져온다
Q8. like 대비 dislike의 수가 가장 적은 영상은 무엇인가? (like, dislike 값이 0인경우는 제외한다)
target = df.loc[(df.likes !=0) & (df.dislikes !=0)]
likes와 dislikes가 0이 아닌 target 생성
num = (target['dislikes']/target['likes']).sort_values().index[0]
오름차순 정렬하고 첫번째 값 가져와서
answer = df.iloc[num].title
그에 대한 타이틀을 가져온다
Q9. 가장많은 트렌드 영상을 제작한 채널의 이름은 무엇인가? (날짜기준, 중복포함)
answer = df.loc[df.channelId ==df.channelId.value_counts().index[0]].channelTitle.unique()
df.channelId.value_counts().index[0]
채널 아이디 기준으로 영상이 많을 때 트렌드 영상이라고 가설을 세운 것
Q10. 20회(20일)이상 인기동영상 리스트에 포함된 동영상의 숫자는?
answer= (df[['title','channelId']].value_counts()>=20).sum()
대괄호를 두번 사용했으니 title과 channelid 기준으로 grouping 된 느낌
기준으로 20개 이상인 동영상
을 sum을 통해 합계를 구함
Q11. 각 데이터의 ‘ct’컬럼을 시간으로 인식할수 있게 datatype을 변경하고 video 데이터의 videoname의 각 value 마다 몇개의 데이터씩 가지고 있는지 확인하라
video['ct'] = pd.to_datetime(video['ct'])
answer = video.videoname.value_counts()
Q12. 수집된 각 video의 가장 최신화 된 날짜의 viewcount값을 출력하라
answer = video.sort_values(['videoname','ct']).drop_duplicates('videoname',keep='last')[['viewcnt','videoname','ct']].reset_index(drop=True)
videoname과 ct기준으로 sorting하고 videoname이 많으니 중복제거하고, 해당 조건에 만족하는 viewcnt, videoname, ct를 가져오면서 인덱스는 초기화
keep=last를 통해 중복 중 가장 최신(오름차순이라) 정보 제공
Q13. Channel 데이터중 2021-10-03일 이후 각 채널의 처음 기록 됐던 구독자 수(subcnt)를 출력하라
channel.ct = pd.to_datetime(channel.ct)
ct 시간 타입으로 변경
target = channel[channel.ct >= pd.to_datetime('2021-10-03')].sort_values(['ct','channelname']).drop_duplicates('channelname')
21년 10월 3일 이후 데이터를 가져와서
channelname기준으로 중복제거하면서 sorting한다 (첫 행이 남는다)
answer = target[['channelname','subcnt']].reset_index(drop=True)
해당 데이터의 channelname과 subcnt를 가져오면서 인덱스는 초기화
Q14. 각채널의 2021-10-03 03:00:00 ~ 2021-11-01 15:00:00 까지 구독자수 (subcnt) 의 증가량을 구하여라
end = channel.loc[channel.ct.dt.strftime('%Y-%m-%d %H') =='2021-11-01 15']
start = channel.loc[channel.ct.dt.strftime('%Y-%m-%d %H') =='2021-10-03 03']
해당 기간에 만족하는 데이터를 가져오고
channel.ct.dt.strftime('%Y-%m-%d %H')은 시간 형태 변경 옵션
end_df = end[['channelname','subcnt']].reset_index(drop=True)
start_df = start[['channelname','subcnt']].reset_index(drop=True)
각각 구한 데이터에서 channelname과 subcnt만 가져온다
end_df.columns = ['channelname','end_sub']
start_df.columns = ['channelname','start_sub']
칼럼 설정
tt = pd.merge(start_df,end_df)
두 데이터 merge
채널 이름 기준으로 붙는다
tt['del'] = tt['end_sub'] - tt['start_sub']
증가량 확인
result = tt[['channelname','del']]
display(result)
Q15. 각 비디오는 10분 간격으로 구독자수, 좋아요, 싫어요수, 댓글수가 수집된것으로 알려졌다. 공범 EP1의 비디오정보 데이터중 수집간격이 5분 이하, 20분이상인 데이터 구간( 해당 시점 전,후) 의 시각을 모두 출력하라
ep_one = video.loc[video.videoname.str.contains('1')].sort_values('ct').reset_index(drop=True)
videoname.str.contains('1')
videoname에 1이 들어간 데이터 모두 가져와서
sort_values('ct').reset_index(drop=True)
수집된 기간(ct)기준으로 sorting 오름차순으로 하며 인덱스 초기화
ep_one[
(ep_one.ct.diff(1) >=datetime.timedelta(minutes=20)) | \
(ep_one.ct.diff(1) <=datetime.timedelta(minutes=5))]
diff는 바로 앞 데이터와의 차이이므로 20분 이상이거나 5분 이하일 때
\는 or 조건
answer = ep_one[ep_one.index.isin([720,721,722,723,1635,1636,1637])]
출력해서 나왔던 인덱스의 전후들을 넣어 출력
Q16. 각 에피소드의 시작날짜(년-월-일)를 에피소드 이름과 묶어 데이터 프레임으로 만들고 출력하라
start_date = video.sort_values(['ct','videoname']).drop_duplicates('videoname')[['ct','videoname']]
시간과 이름 기준으로 sorting(오름차순), 이름 중복제거 (첫번째가 남음)해서 ct와 videoname을 가져온다
start_date['date'] = start_date.ct.dt.date
date 칼럼 만들고 date 형식
answer = start_date[['date','videoname']]
display(answer)
Q17. “공범” 컨텐츠의 경우 19:00시에 공개 되는것으로 알려져있다. 공개된 날의 21시의 viewcnt, ct, videoname 으로 구성된 데이터 프레임을 viewcnt를 내림차순으로 정렬하여 출력하라
video['time']= video.ct.dt.hour
비디오 time에 시간만 가져온다
answer = video.loc[video['time'] ==21] \
.sort_values(['videoname','ct'])\
.drop_duplicates('videoname') \
.sort_values('viewcnt',ascending=False)[['videoname','viewcnt','ct']]\
.reset_index(drop=True)
time이 21인 데이터를 videoname과 ct로 오름차순 sorting 후 videoname 기준으로 중복 제거 후 viewcnt 기준으로 내림차순으로 sorting 해준다
Q18. video 정보의 가장 최근 데이터들에서 각 에피소드의 싫어요/좋아요 비율을 ratio 컬럼으로 만들고 videoname, ratio로 구성된 데이터 프레임을 ratio를 오름차순으로 정렬하라
target = video.sort_values('ct').drop_duplicates('videoname',keep='last')
오름차순이므로 keep=last를 통해 최신 데이터 보존
target['ratio'] =target['dislikecnt'] / target['likecnt']
answer = target.sort_values('ratio')[['videoname','ratio']].reset_index(drop=True)
Q19. 2021-11-01 00:00:00 ~ 15:00:00까지 각 에피소드별 viewcnt의 증가량을 데이터 프레임으로 만드시오
start = pd.to_datetime("2021-11-01 00:00:00")
end = pd.to_datetime("2021-11-01 15:00:00")
datetime 형태로 변환
target = video.loc[(video["ct"] >= start) & (video['ct'] <= end)].reset_index(drop=True)
두 조건을 만족하는 데이터 가져온다
def check(x):
result = max(x) - min(x)
return result
answer = target[['videoname','viewcnt']].groupby("videoname").agg(check)
연산자여서 agg를 사용해야한다
Q20. video 데이터 중에서 중복되는 데이터가 존재한다. 중복되는 각 데이터의 시간대와 videoname 을 구하여라
answer = video[video.index.isin(set(video.index) - set(video.drop_duplicates().index))]
set(video.index)는 video.index 모든 값을 가져온다
전체 데이터 - 중복 데이터니까 중복된 index만 남게된다
result = answer[['videoname','ct']]
display(result)
중복체크 : video[(video['videoname'].str.contains('공범 EP1')) & (video['ct'] == pd.to_datetime('2021-10-13 09:41:37'))]
Q21. 주어진 전체 기간의 각 나라별 골득점수 상위 5개 국가와 그 득점수를 데이터프레임형태로 출력하라
df.groupby('Country')['Goals'].sum()
출력한 후
result = df.groupby('Country', as_index=False)['Goals'].sum().sort_values(by=['Goals'],ascending=False).head()
display(result)
Q22. 주어진 전체기간동안 골득점을 한 선수가 가장 많은 나라 상위 5개 국가와 그 선수 숫자를 데이터 프레임 형식으로 출력하라
result = df.groupby('Country').size().sort_values(ascending=False).head(5)
print(result)
Q23. Years 컬럼은 년도 -년도 형식으로 구성되어있고, 각 년도는 4자리 숫자이다. 년도 표기가 4자리 숫자로 안된 케이스가 존재한다. 해당 건은 몇건인지 출력하라
df['yearLst'] = df.Years.str.split('-')
def checkFour(x):
for value in x:
if len(str(value)) != 4:
return False
return True
****df['check'] = df['yearLst'].apply(checkFour)
result = len(df[df.check ==False])
reult
Q24. Q23에서 발생한 예외 케이스를 제외한 데이터프레임을 df2라고 정의하고 데이터의 행의 숫자를 출력하라 (아래 문제부터는 df2로 풀이하겠습니다)
df2 = df[df.check ==True].reset_index(drop=True)
Q25. 월드컵 출전횟수를 나타내는 ‘LenCup’ 컬럼을 추가하고 4회 출전한 선수의 숫자를 구하여라
df2['LenCup'] =df2['yearLst'].str.len()
리스트형식으로 있는 yearlst의 갯수 셈
result = df2['LenCup'].value_counts()[4]
lencup을 기준으로 value_counts를 세었을 때 4이상
Q26. Yugoslavia 국가의 월드컵 출전횟수가 2회인 선수들의 숫자를 구하여라
result = len(df2[(df2.LenCup==2) & (df2.Country =='Yugoslavia')])
Q28. 이름에 ‘carlos’ 단어가 들어가는 선수의 숫자는 몇 명인가? (대, 소문자 구분 x)
result = len(df2[df2.Player.str.lower().str.contains('carlos')])
str.lower()을 통해 모두 소문자로 변환한 데이터로 불러와서~
Q29. 월드컵 출전 횟수가 1회뿐인 선수들 중에서 가장 많은 득점을 올렸던 선수는 누구인가?
result = df2[df2.LenCup==1].sort_values('Goals',ascending=False).Player.values[0]
내림차순 정렬해서 player.values 중 (0)번
Q30. 월드컵 출전횟수가 1회 뿐인 선수들이 가장 많은 국가는 어디인가?
result= df2[df2.LenCup==1].Country.value_counts().index[0]
Q31. 대여일자별 데이터의 수를 데이터프레임으로 출력하고, 가장 많은 데이터가 있는 날짜를 출력하라
result = df['대여일자'].value_counts().sort_index().to_frame()
대여일자별로 센 다음
sort_index는 인덱스 기준으로 sorting한 것 (날짜 순으로 정렬됨)
answer = result[result.대여일자 == result.대여일자.max()].index[0]
Q32. 각 일자의 요일을 표기하고 (‘Monday’ ~’Sunday’) ‘day_name’컬럼을 추가하고 이를 이용하여 각 요일별 이용 횟수의 총합을 데이터 프레임으로 출력하라
df['대여일자'] = pd.to_datetime(df['대여일자'])
df['day_name'] = df['대여일자'].dt.day_name()
result = df.day_name.value_counts().to_frame()
데이터 프레임으로 표현하라 해서 to_frame() 입력
Q33. 각 요일별 가장 많이 이용한 대여소의 이용횟수와 대여소 번호를 데이터 프레임으로 출력하라
result = df.groupby(['day_name','대여소번호']).size().to_frame('size').sort_values(['day_name','size'],ascending=False).reset_index()
요일별 대여소번호 기준으로 사이즈를 세고 그 사이즈 frame으로 변경하고
day_name과 size 기준으로 내림차순 진행한 후 인덱스 초기화
answer = result.drop_duplicates('day_name',keep='first').reset_index(drop=True)
Q34. 나이대별 대여구분 코드의 (일일권/전체횟수) 비율을 구한 후 가장 높은 비율을 가지는 나이대를 확인하라. 일일권의 경우 일일권 과 일일권(비회원)을 모두 포함하라
daily = df[df.대여구분코드.isin(['일일권','일일권(비회원)'])].연령대코드.value_counts().sort_index()
total = df.연령대코드.value_counts().sort_index()
ratio = (daily /total).sort_values(ascending=False)
print(ratio)
print('max ratio age ',ratio.index[0])
Q35. 나이대별 이동거리의 평균을 구하여라
result = df[['연령대코드','이동거리']].groupby(['연령대코드']).mean()
Q36.연령대 코드가 20대인 데이터를 추출하고,이동거리값이 추출한 데이터의 이동거리값의 평균 이상인 데이터를 추출한다.최종 추출된 데이터를 대여일자, 대여소 번호 순서로 내림차순 정렬 후 1행부터 200행까지의 탄소량의 평균을 소숫점 3째 자리까지 구하여라
tw = df[df.연령대코드 =='20대'].reset_index(drop=True)
tw_mean = tw[tw.이동거리 >= tw.이동거리.mean()].reset_index(drop=True)
tw_mean['탄소량'] =tw_mean['탄소량'].astype('float')
target =tw_mean.sort_values(['대여일자','대여소번호'], ascending=False).reset_index(drop=True).iloc[:200].탄소량
result = round(target.sum()/len(target),3)
round는 소수점 나타내는 문법
Q37. 6월 7일 ~10대의 “이용건수”의 중앙값은?
df['대여일자'] =pd.to_datetime(df['대여일자'])
result = df[(df.연령대코드 =='~10대') & (df.대여일자 ==pd.to_datetime('2021-06-07'))].이용건수.median()
Q38. 평일 (월~금) 출근 시간대(오전 6,7,8시)의 대여소별 이용 횟수를 구해서 데이터 프레임 형태로 표현한 후 각 대여시간별 이용 횟수의 상위 3개 대여소와 이용횟수를 출력하라
target = df[(df.day_name.isin(['Tuesday', 'Wednesday', 'Thursday', 'Friday','Monday'])) & (df.대여시간.isin([6,7,8]))]
result = target.groupby(['대여시간','대여소번호']).size().to_frame('이용 횟수')
answer = result.sort_values(['대여시간','이용 횟수'],ascending=False).groupby('대여시간').head(3)
Q39. 이동거리의 평균 이상의 이동거리 값을 가지는 데이터를 추출하여 추출데이터의 이동거리의 표본표준편차 값을 구하여라
result = df[df.이동거리 >= df.이동거리.mean()].reset_index(drop=True).이동거리.std()
Q40. 남성(‘M’ or ‘m’)과 여성(‘F’ or ‘f’)의 이동거리값의 평균값을 구하여라
df['sex'] = df['성별'].map(lambda x: '남' if x in ['M','m'] else '여')
answer = df[['sex','이동거리']].groupby('sex').mean()
Q41.데이터는 2018년도와 2019년도의 전세계 행복 지수를 표현한다. 각년도의 행복랭킹 10위를 차지한 나라의 행복점수의 평균을 구하여라
result = df[df.행복랭킹 ==10]['점수'].mean()
Q42.데이터는 2018년도와 2019년도의 전세계 행복 지수를 표현한다. 각년도의 행복랭킹 50위이내의 나라들의 각각의 행복점수 평균을 데이터프레임으로 표시하라
result = df[df.행복랭킹<=50]['년도','점수']].groupby('년도').mean()
Q43.2018년도 데이터들만 추출하여 행복점수와 부패에 대한 인식에 대한 상관계수를 구하여라
result = df[df.년도 ==2018]['점수','부패에 대한인식']].corr().iloc[0,1]
corr을 통해 상관계수 가져와서 0번째 행의 첫번째 칼럼
Q44.2018년도와 2019년도의 행복랭킹이 변화하지 않은 나라명의 수를 구하여라
result = len(df[['행복랭킹','나라명']]) - len(df[['행복랭킹','나라명']].drop_duplicates())
Q45. 2019년도 데이터들만 추출하여 각변수간 상관계수를 구하고 내림차순으로 정렬한 후 상위 5개를 데이터 프레임으로 출력하라. 컬럼명은 v1,v2,corr으로 표시하라
zz = df[df.년도 ==2019].corr().unstack().to_frame().reset_index().dropna()
result = zz[zz[0] !=1].sort_values(0,ascending=False).drop_duplicates(0)
1은 자기자신과 상관계수니까
칼럼명이 0이라
answer = result.head(5).reset_index(drop=True)
answer.columns = ['v1','v2','corr']
칼럼명 재정의
Q46. 각 년도별 하위 행복점수의 하위 5개 국가의 평균 행복점수를 구하여라
result = df.groupby('년도').tail(5).groupby('년도').mean()[['점수']]
Q47. 2019년 데이터를 추출하고 해당데이터의 상대 GDP 평균 이상의 나라들과 평균 이하의 나라들의 행복점수 평균을 각각 구하고 그 차이값을 출력하라
df2 = df[df['년도'] == 2019]
over = df2[df2.상대GDP >= df2.상대GDP.mean()]['점수'].mean()
under = df2[df2.상대GDP <= df2.상대GDP.mean()]['점수'].mean()
under = df2[df2.상대GDP <= df2.상대GDP.mean()]['점수'].mean()
Q48. 각년도의 부패에 대한인식을 내림차순 정렬했을때 상위 20개 국가의 부패에 대한인식의 평균을 구하여라
result = df.sort_values(['년도','부패에 대한인식'],ascending=False).groupby('년도').head(20).groupby(['년도']).mean()[['부패에 대한인식']]
Q49.2018년도 행복랭킹 50위 이내에 포함됐다가 2019년 50위 밖으로 밀려난 국가의 숫자를 구하여라
result = set(df[(df.년도==2018) & (df.행복랭킹 <=50)].나라명) -set(df[(df.년도==2019) & (df.행복랭킹 <=50)].나라명)
answer = len(result)
Q50. 2018년,2019년 모두 기록이 있는 나라들 중 년도별 행복점수가 가장 증가한 나라와 그 증가 수치는?
count = df.나라명.value_counts()
target = count[count>=2].index
df2 =df.copy()
multiple = df2[df2.나라명.isin(target)].reset_index(drop=True)
multiple.loc[multiple['년도']==2018,'점수'] = multiple[multiple.년도 ==2018]['점수'].values * (-1)
년도별 행복점수가 가장 증가한 나라를 구하기 위해서 19년도 데이터에서 18년도 데이터를 붙이기 위해 multiple 사용
result = multiple.groupby('나라명').sum()['점수'].sort_values().to_frame().iloc[-1]
iloc[-1]이라 가장 마지막 값
Q51. DateTime컬럼을 통해 각 월별로 몇개의 데이터가 있는지 데이터 프레임으로 구하여라
df['DateTime'] = pd.to_datetime(df['DateTime'])
result = df['DateTime'].dt.month.value_counts().sort_index().to_frame()
Q52.3월달의 각 시간대별 온도의 평균들 중 가장 낮은 시간대의 온도를 출력하라
target = df[df.DateTime.dt.month ==3]
result = target.groupby(target.DateTime.dt.hour)['Temperature'].mean().sort_values().values[0]
Q53.3월달의 각 시간대별 온도의 평균들 중 가장 높은 시간대의 온도를 출력하라
target = df[df.DateTime.dt.month ==3]
result = target.groupby(target.DateTime.dt.hour)['Temperature'].mean().sort_values().values[-1]
Q54. Zone 1 Power Consumption 컬럼의 value값의 크기가 Zone 2 Power Consumption 컬럼의 value값의 크기보다 큰 데이터들의 Humidity의 평균을 구하여라
result = df[df['Zone 1 Power Consumption'] > df['Zone 2 Power Consumption']].Humidity.mean()
Q55. 각 zone의 에너지 소비량의 상관관계를 구해서 데이터 프레임으로 표기하라
result = df.iloc[:,-3:].corr()
Q56. Temperature의 값이 10미만의 경우 A, 10이상 20미만의 경우 B,20이상 30미만의 경우 C, 그 외의 경우 D라고 할때 각 단계의 데이터 숫자를 구하여라
def split_data(x):
if x<10:
return "A”
elif x<20:
return 'B’
elif x<30:
return 'C’
else:
return 'D’
df['sp'] = df.Temperature.map(split_data)
result = df['sp'].value_counts()
Q57. 6월 데이터중 12시의 Temperature의 표준편차를 구하여라
result =df[(df.DateTime.dt.month ==6) & (df.DateTime.dt.hour ==12)].Temperature.std()
Q59. Temperature의 평균이상의 Temperature의 값을 가지는 데이터를 Temperature를 기준으로 정렬 했을때 4번째 행의 Humidity 값은?
result = df[df.Temperature >= df.Temperature.mean()].sort_values('Temperature').Humidity.values[3]
Q60. Temperature의 중간값 이상의 Temperature의 값을 가지는 데이터를Temperature를 기준으로 정렬 했을때 4번째 행의 Humidity 값은?
result = df[df.Temperature >= df.Temperature.median()].sort_values('Temperature').Humidity.values[3]
Q61. Legendary 컬럼은 전설포켓몬 유무를 나타낸다.전설포켓몬과 그렇지 않은 포켓몬들의 HP평균의 차이를 구하여라
target = df.groupby('Legendary')['HP'].mean()
result = target.values[1] -target.values[0]
Q62. Type 1은 주속성 Type 2 는 부속성을 나타낸다. 가장 많은 부속성 종류는 무엇인가?
result = df['Type 2'].value_counts().index[0]
Q63. 가장 많은 Type 1 의 종의 평균 Attack 을 평균 Defense로 나눈값은?
Max = df['Type 1'].value_counts().index[0]
result = df[df['Type 1']== Max].Attack.mean() /df[df['Type 1']== Max].Defense.mean()
Q65. ‘HP’, ‘Attack’, ‘Defense’, ‘Sp. Atk’, ‘Sp. Def’, ‘Speed’ 간의 상관 계수중 가장 절댓값이 큰 두 변수와 그 값을 구하여라
target = df[[ 'HP', 'Attack', 'Defense', 'Sp. Atk', 'Sp. Def', 'Speed']].corr().unstack().reset_index().rename(columns={0: "corr"})
result = target[target['corr']!=1].sort_values('corr',ascending=False).iloc[0]
각 Generation의 Attack으로 오름차순 정렬시 상위 3개 데이터들(18개)의 Attack의 전체 평균을 구하여라
result = df.sort_values(['Generation','Attack']).groupby('Generation').head(3).Attack.mean()
Q68. 주속성(Type 1)별 포켓몬의 평균 HP는 얼마인가?
answer = df.groupby('Type 1')['HP'].mean().sort_values(ascending=False)
Q69. 주속성(Type 1) 중 평균 특수공격력(Sp. Atk)이 가장 높은 속성은 무엇인가?
highest_sp_atk_type = df.groupby('Type 1')['Sp. Atk'].mean().idxmax()
idxmax는 바로 앞 값(df.groupby('Type 1')['Sp. Atk'].mean()) 중 가장 큰 index를 가져오는 것이다
Q70. 부속성(Type 2)이 없는 포켓몬은 몇 마리인가?
count_no_secondary_type = df['Type 2'].isna().sum()
Q71. 전체데이터의 수축기혈압(최고) - 이완기혈압(최저)의 평균을 구하여라
result = (df['수축기혈압(최고) : mmHg'] - df['이완기혈압(최저) : mmHg']).mean()
Q72. 50~59세의 신장평균을 구하여라
result = df[(df.측정나이 <60) & (df.측정나이>=50)].iloc[:,2].mean()
Q73. 연령대 (20~29 : 20대 …) 별 인원수를 구하여라
df['연령대'] =df.측정나이 //10 *10
result = df['연령대'].value_counts()
Q74. 연령대 (20~29 : 20대 …) 별 등급의 숫자를 데이터 프레임으로 표현하라
result = df.groupby(['연령대','등급'],as_index=False).size()
Q75. 남성 중 A등급과 D등급의 체지방률 평균의 차이(큰 값에서 작은 값의 차)를 구하여라
result = abs(df[(df.측정회원성별 =='M') &(df.등급 =='A')].iloc[:,4].mean() -df[(df.측정회원성별 =='M') &(df.등급 =='D')].iloc[:,4].mean())
무엇이 큰 값인지 모르니 절대값 사용
Q76.여성 중 A등급과 D등급의 체중의 평균의 차이(큰 값에서 작은 값의 차)를 구하여라
result = abs(df[(df.측정회원성별 =='F') &(df.등급 =='A')].iloc[:,3].mean() -df[(df.측정회원성별 =='F') &(df.등급 =='D')].iloc[:,3].mean())
Q77. bmi는 자신의 몸무게(kg)를 키의 제곱(m)으로 나눈값이다. 데이터의 bmi 를 구한 새로운 컬럼을 만들고 남성의 bmi 평균을 구하여라
df['bmi'] = df['체중 : kg'] / (df['신장 : cm']/100) **2
result = df[df.측정회원성별 =='M'].bmi.mean()
Q78.bmi보다 체지방율이 높은 사람들의 체중평균을 구하여라
result =df[df.bmi <df['체지방율 : %']]['체중 : kg'].mean()
Q79.남성과 여성의 악력 평균의 차이를 구하여라
target= df.groupby('측정회원성별')['악력D : kg'].mean()
result = target.M - target.F
Q80. 남성과 여성의 교차윗몸일으키기 횟수의 평균의 차이를 구하여라
target= df.groupby('측정회원성별')['교차윗몸일으키기 : 회'].mean()
result = target.M - target.F
Q81. 여름철(6월,7월,8월) 이화동이 수영동보다 높은 기온을 가진 시간대는 몇개인가?
df.time = pd.to_datetime(df.time)
summer = df.loc[df.time.dt.month.isin([6,7,8])].reset_index(drop=True)
answer = len(summer.loc[summer['이화동기온'] > summer['수영동기온']])
Q82. 이화동과 수영동의 최대강수량의 시간대를 각각 구하여라
answer1 = df.loc[df['이화동강수']==df['이화동강수'].max()].time.values
answer2 = df.loc[df['수영동강수']==df['수영동강수'].max()].time.values
print(answer1,answer2)
Q83. 남성 이탈(Exited)이 가장 많은 국가(Geography)는 어디이고 이탈 인원은 몇명인가?
answer = df.loc[df.Gender=='Male'].groupby(['Geography'])['Exited'].sum().sort_values(ascending=False).head(1)
Excited 내림차순
Q84. 카드를 소유(HasCrCard ==1)하고 있으면서 활성멤버(IsActiveMember ==1) 인 고객들의 평균 나이를 소숫점이하 4자리까지 구하여라?
answer = df.loc[(df.HasCrCard==1) &(df.IsActiveMember==1)].Age.mean()
print(round(answer,4))
Q85. Balance 값이 중간값 이상을 가지는 고객들의 CreditScore의 표준편차를 소숫점이하 3자리까지 구하여라
answer =df.loc[df.Balance >= df.Balance.median()].CreditScore.std()
Q86. 수축기혈압과 이완기 혈압기 수치의 차이를 새로운 컬럼(‘혈압차’) 으로 생성하고, 연령대 코드별 각 그룹 중 ‘혈압차’ 의 분산이 5번째로 큰 연령대 코드를 구하여라
df['혈압차'] =df['수축기혈압'] -df['이완기혈압']
answer = df.groupby('연령대코드(5세단위)')['혈압차'].var().sort_values()
print(answer.index[-5])
Q87. 비만도를 나타내는 지표인 WHtR는 허리둘레 / 키로 표현한다. 일반적으로 0.58이상이면 비만으로 분류한다. 데이터중 WHtR 지표상 비만인 인원의 남/여 비율을 구하여라
df['비만']=df['허리둘레']/df['신장(5Cm단위)']
data = df.loc[df['비만']>=0.58].성별코드.value_counts()
answer = data['M']/data['F']
Q88. Vehicle_Age 값이 2년 이상인 사람들만 필터링 하고 그중에서 Annual_Premium 값이 전체 데이터의 중간값 이상인 사람들을 찾고, 그들의 Vintage값의 평균을 구하여라
answer = df[(df['Vehicle_Age']=='> 2 Years') & (df['Annual_Premium'] >= df['Annual_Premium'].median())]['Vintage'].mean()
Q89. vehicle_age에 따른 각 성별(gender)그룹의 Annual_Premium값의 평균을 구하여 아래 테이블과 동일하게 구현하라
meandf = df.groupby(['Gender','Vehicle_Age'],as_index = False)['Annual_Premium'].mean()
meandf.pivot(index='Vehicle_Age',columns='Gender',values='Annual_Premium')
Q90. price_range 의 각 value를 그룹핑하여 각 그룹의 n_cores 의 빈도가 가장높은 value와 그 빈도수를 구하여라
answer =df[['price_range','n_cores']].groupby(['price_range','n_cores']).size().sort_values(0).groupby(level=0).tail(1)
Q91. price_range 값이 3인 그룹에서 상관관계가 2번째로 높은 두 컬럼과 그 상관계수를 구하여라
cordf = df.loc[df['price_range']==3].corr().unstack().sort_values(ascending=False)
answer = cordf.loc[cordf!=1].reset_index().iloc[1]
두번째로 높아서 1
Q92. Arrival Delay in Minutes 컬럼이 결측치인 데이터들 중 satisfaction col에서‘neutral or dissatisfied’ 보다 ‘satisfied’의 수가 더 높은 Class는 어디 인가?
answer =df.loc[df['Arrival Delay in Minutes'].isnull()].groupby(['Class','satisfaction'],as_index=False).size().pivot(index='Class',columns='satisfaction')
result =answer[answer['size']['neutral or dissatisfied'] < answer['size']['satisfied']]
Q93. ph값은 상당히 많은 결측치를 포함한다. 결측치를 제외한 나머지 데이터들 중 사분위값 기준 하위 25%의 값들의 평균값은?
target = df['ph'].dropna()
answer =target.loc[target <= target.quantile(0.25)].mean()
Q94. 흡연자와 비흡연자 각각 charges의 상위 10% 그룹의 평균의 차이는?
high = train.loc[train.smoker =='yes'].charges.quantile(0.9)
high2 = train.loc[train.smoker =='no'].charges.quantile(0.9)
mean_yes = train.loc[(train.smoker =='yes') &(train.charges >=high)].charges.mean()
mean_no = train.loc[(train.smoker =='no') &(train.charges >=high2)].charges.mean()
answer = mean_yes - mean_no
Q95. bedrooms 의 빈도가 가장 높은 값을 가지는 데이터들의 price의 상위 10%와 하위 10%값의 차이를 구하여라
answer1 = df.loc[df.bedrooms ==df.bedrooms.value_counts().index[0]].price.quantile(0.9)
answer2 = df.loc[df.bedrooms ==df.bedrooms.value_counts().index[0]].price.quantile(0.1)
print(answer1 - answer2)
Q96. Serial No. 컬럼을 제외하고 ‘Chance of Admit’을 종속변수, 나머지 변수를 독립변수라 할때, 랜덤포레스트를 통해 회귀 예측을 할 떄 변수중요도 값을 출력하라 (시드값에 따라 순서는 달라질수 있음)
from sklearn.ensemble import RandomForestRegressor
df_t = df.drop([df.columns[0]],axis=1)
x = df_t.drop([df.columns[-1]],axis=1)
y = df_t[df.columns[-1]]
df.drop은 삭제한다는 뜻
0번째 칼럼 삭제하고
ml = RandomForestRegressor()
ml.fit(x,y)
result=pd.DataFrame({'importance':ml.featureimportances},x.columns).sort_values('importance',ascending=False)
display(result)
Q97. quality 값이 3인 그룹과 8인 데이터그룹의 각 컬럼별 독립변수의 표준편차 값의 차이를 구할때 그값이 가장 큰 컬럼명을 구하여라
answer = (df.loc[df.quality ==8].std() -df.loc[df.quality ==3].std()).sort_values().index[-1]
Q98. 남성들의 연령대별 (10살씩 구분 0-9세, 10-19세 …) Na_to_K값의 평균값을 구해서 데이터 프레임으로 표현하여라
pre = df.loc[df.Sex=='M']
pre2= pre.copy()
pre2['Age2'] = pre.Age//10 *10
answer =pre2.groupby('Age2')['Na_to_K'].mean().to_frame()
Q99. 데이터의 Risk 값에 따른 score_a와 score_b의 평균값을 구하여라
answer =df.groupby('Risk')[['Score_A','Score_B']].mean()
Q100. pose값에 따른 각 motion컬럼의 중간값의 가장 큰 차이를 보이는 motion컬럼은 어디이며 그값은?
t= df.groupby('pose').median().T
T는 transpose 즉, 행 열 변환
dfs = abs(t[0] - t[1]).sort_values().reset_index()
dfs[dfs[0] ==dfs[0].max()]['index'].values
Q101. 정보(row수)가 가장 많은 상위 3차종(model)의 price값의 각 평균값은?
answer =df.loc[df.model.isin(df.model.value_counts().index[:3])].groupby('model')['price'].mean().to_frame()
Q102. Outcome 값에 따른 각 그룹의 각 컬럼의 평균 차이를 구하여라
answer = df.groupby('Outcome').mean().diff().iloc[1,:]
Q103. 매년 5월달의 open가격의 평균값을 데이터 프레임으로 표현하라
df['Date'] =pd.to_datetime(df['Date'])
target = df.groupby(df['Date'].dt.strftime('%Y-%m')).mean()
answer = target.loc[target.index.str.contains('-05')].Open
Q104. Tm 컬럼은 각 팀의 이름을 의미한다. TOR팀의 평균나이를 소수 4째 자리까지 구하여라
result = round(df[df.Tm =='TOR'].Age.mean(),4)
Q105. Pos 컬럼은 포지션을 의미한다. 전체 선수 중 최소나이대의 선수들을 필터하고 그들 중 가장 많은 포지션은 무엇인지 확인하라
result = df[df.Age==df.Age.min()].Pos.value_counts().index[0]
Q106. 선수들의 이름은 first_name+ 공백 + last_name으로 이루어져 있다. 가장 많은 first_name은 무엇이며 몇 회 발생하는지 확인하라
result= df['Player'].str.split().str[0].str.lower().value_counts().index[0]
split() 이면 공백 기준
Q107. PTS컬럼은 경기당 평균득점수 이다. 각포지션별로 경기당 평균득점수의 평균을 구하여라
result = df.groupby('Pos')['PTS'].mean().sort_values()
Q109. G컬럼은 참여한 경기의 숫자이다. 각 팀별로 가장 높은 경기참여 수를 가진 선수들의 경기 참여 숫자의 평균을 구하여라
result = df.sort_values(['Tm','G']).groupby('Tm').tail(1).G.mean()
Q110. Tm의 값이 MIA이며 Pos는 C또는 PF인 선수의 MP값의 평균은?
result = df[(df.Tm =='MIA') & (df.Pos.isin(['C','PF']))].MP.mean()
Q111. 전체 데이터중 G의 평균값의 1.5배 이상인 데이터들만 추출했을때 3P값의 평균은?
result = df[df.G >= df.G.mean()*1.5]['3P'].mean()
Q112. Age의 평균 이상인 그룹과 평균 미만인 그룹간의 G값의 평균의 차이는?
result = df[df.Age >= df.Age.mean()].G.mean() - df[df.Age < df.Age.mean()].G.mean()
Q113. 평균나이가 가장 젊은 팀은 어디인가
result = df.groupby('Tm')['Age'].mean().sort_values().index[0]
Q114. Pos그룹별 평균 MP값을 구하여라
result = df.groupby('Pos')['MP'].mean()
01.Data 형태 확인
import pandas as pd
데이터 형태 확인
df.shape
df.info()
Null값 확인
df.isnull().sum()
02.Unique한 Value별 카운팅
len(df['col'].unique()) >> 카운팅
df['col'].unique()
각 요소 보기
03.DataFrame 특정값 치환
import numpy as np
df.replace(-200, np.NaN)
04.Null 값 이전 값으로 채워넣기
import numpy as np
df.fillna(method='ffill')
05.DataFrame 특정 col만 가져오기
****> df = df[['col1', 'col2']]
06.조건에 맞는 DataFrame 출력
df[ (df['T'] >= 25) & (df['T'] <= 27) ]
07.오름차순, 내림차순 정렬
df['col'].sort_values(ascending=False)
ascending = False(내림차순), default(오름차순)
08.특정값이 포함된 Data 찾기
df[df['col'].astype(str).str.contains('text')]
문자열이 아닐 수도 있으니까 astype(str) 를 해준다
09.특정 조건 만족하는 값, 변경하기
import numpy as np
np.where(df['col'] <= 5, 1, 0)
if as를 편하게 하는 방법
5이하일 때는 1, 아니면 0으로 바꿔준다
10.groupby 활용 카운팅
df['y'].groupby(df['job']).value_counts()
11.pivot table 활용 데이터 처리
df_job = pd.pivot_table(df_job,
index = 'index',
columns = 'col',
values = 'value')
12.inf(무한대) 데이터 null 처리
df['col'].replace([np.inf, -np.inf], np.nan)
양의 무한대와 음의 무한대를 null값으로 치환하겠다는 뜻
13.lag 데이터 생성
df['col'].shift(1)
순방향 : + n, 역방향 : ㅍ
14.중복 데이터 처리
df.drop_duplicates(['col'], keep = 'first', inplace=True)
15.문자열 데이터 앞 공백 제거
df['col'].str.lstrip()
15.날짜 데이터 형식 변경
df["Date"].dt.strftime("%Y-%m")
16.list 중복 없애기
all_list = list(df['start']) + list(df['end'])
unique_list = set(all_list)
Data Visualization (데이터 시각화)
연속형(Numeric) 변수 분포 확인
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
sns.displot(df['col']);
displot : 히스토그램과 kdeplot을 만들 수 있어서, 자주 사용
print("col :", df['col'].mean())
분포의 평균도 같이 출력
Plot size 조절
> import matplotlib.pyplot as plt
plt.gcf().set_size_inches(20, 5)
****>> (가로, 세로)
산점도(Scatter plot) 그리기
import seaborn as sns
sns.scatterplot(x=df['x'], y=df['y'], hue = df['hue'], data=df)hue는 색상
기본 line plot 그리기
import matplotlib.pyplot as plt
plt.plot(df['x'], df['y'], label='label')
for문 활용 distplot 다중 출력
import matplotlib.pyplot as plt
for i in range(1,13):
plt.subplot(3,4,i)
plt.grid(False)
sns.distplot(df.iloc[:,i])subplot은 격자선 (3행 4열)
plt.gcf().set_size_inches(20, 10)
plt.tight_layout()
plt.show()
이중 축 그래프 그리기
import matplotlib.pyplot as plt
fig, ax1 = plt.subplots()
ax1.plot(df['x'], df['y'], color='green', label='label1')
ax2 = ax1.twinx()
ax2.plot(df['x'], df['y'], color='deeppink', label='label2')
fig.legend()
plt.gcf().set_size_inches(25, 5)
plt.show()
pairplot 상관관계 분석
import seaborn as sns
df_pair = df[['col1', 'col2', 'col3', 'col4']]모든 변수 조합에 관한 Scatter plot
변수가 많으면 오래걸리기 때문에 col을 끊어서 활용
sns.pairplot(df_pair)
plt.show()
Heat map 상관관계 분석
import seaborn as sns
df_pair = df[['col1', 'col2', 'col3', 'col4']]
sns.heatmap(df_pair.corr(), vmin = -1, vmax = +1, annot = True, cmap = 'coolwarm');
annot 실제 상관계수 적을 것이냐
그래프에 수직, 수평선 추가 및 길이 조절
import seaborn as sns
import matplotlib.pyplot as plt
sns.scatterplot(data=df,x='x',y='y', s=50, linewidth=0);
수직선 추가
plt.vlines(-2, ymin=-2, ymax=2, color='r', linewidth=2);
plt.vlines(2, ymin=-2, ymax=2, color='r', linewidth=2);
수평선 추가
plt.hlines(-2, xmin=-2, xmax=2, color='r', linewidth=2);
plt.hlines(2, xmin=-2, xmax=2, color='r', linewidth=2);
catplot 그리기
import seaborn as sns
import matplotlib.pyplot as plt
%matplotlib inline
plt.style.use(['dark_background'])
sns.catplot(x="x", hue="y", kind="count",palette="pastel", edgecolor=".6",data=df);
plt.gcf().set_size_inches(25, 3)팔레트 : 색상, edgecolor : 바 그래프
그래프 특정 값에 색상 입히기
import numpy as np
import matplotlib.pyplot as plt
df['vol_color'] = np.where(df['Volume_issue']==1, 'red', 'gray')
colors=list(df['vol_color'])
print(colors)
plt.figure(figsize=(10, 8))
plt.subplot(2,1,1)
plt.plot(df['Date'], df['Close'], 'o-', ms=1, lw=0.5, label='Close')
plt.legend()
plt.subplot(2,1,2)
plt.bar(df['Date'], df['Volume'], label='volume', color=colors)
plt.legend()
bar plot 그리기
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
sns.barplot(x='arrival_date_month', y='hotel', hue='arrival_date_year', data = df_reservation,
order = ['01.January', '02.February', '03.March', '04.April', '05.May', '06.June', '07.July', '08.August', '09.September', '10.October', '11.November', '12.December']);
order는 순서를 미리 정해주는 것
plt.gcf().set_size_inches(20, 5);
Data Analysis & Modeling
Train/Test set 분할
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn import metrics모델링을 학습하기 위한 Feature(X)와 Y데이터를 구분하는 단계
X=df_merge.drop(['y'], axis=1)
Y=df_merge['y']데이터해서 예측하고자하는 y데이터를 x데이터에서 없애주고 Y데이터에 넣는다
x_train, x_test, y_train, y_test = train_test_split(X, Y, test_size=0.3, stratify=Y)
훈련함수 배정
stratify는 이진분류문제 해결할 때 나눴던 train셋과 test셋 비율
print(x_train.shape)
print(y_train.shape)
print(x_test.shape)
print(y_test.shape)
모델 학습 및 예측
모델 학습
rfc = RandomForestClassifier(random_state=123456)
rfc.fit(x_train, y_train)rfc는 모델의 빈껍데기
random_state는 모델링할 때 난수 고정
fit을 통해 위에 만들어둔 train set을 넣는다
예측
예측은 학습에 사용된 Data와 Test Data 모두 예측하고 평가함(※ 과적합 여부 판별)
y_pred_train = rfc.predict(x_train)
y_pred_test = rfc.predict(x_test)
이진분류 모델 성능 확인
from sklearn.metrics import classification_report
print(classification_report(y_train, y_pred_train))
print(classification_report(y_test, y_pred_test))classification_report는 1과 0 예측 등 이진분류할 때 주로 사용
하이퍼 파라미터 튜닝
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import GridSearchCVGridSearchCV가 대표적 튜닝 방법
params = { 'n_estimators' : [400, 500],
'max_depth' : [6, 8, 10, 12]
}테스트할 하이퍼 파라미터 범위 사전 설정
RandomForestClassifier 객체 생성 후 GridSearchCV 수행
rf_clf = RandomForestClassifier(random_state = 123456, n_jobs = -1)
grid_cv = GridSearchCV(rf_clf, param_grid = params, cv = 3, n_jobs = -1, scoring='recall')
grid_cv.fit(x_train, y_train)CV는 모델 여러번 테스트하며 검증하는 것, 여기서는 cv=3이므로 3번 돌린다는 의미
print('최적 하이퍼 파라미터: ', gridcv.best_params)
print('최고 예측 정확도: {:.4f}'.format(gridcv.best_score))
중요 변수 파악(Feature Importance)
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
rfc → 생성한 Model에 name 기재
ftrimportances_values = rfc.feature_importances
ftr_importances = pd.Series(ftr_importances_values, index = x_train.columns)
ftr_top20 = ftr_importances.sort_values(ascending=False)[:20]
plt.figure(figsize=(8,6))
plt.title('Feature Importances')
sns.barplot(x=ftr_top20, y=ftr_top20.index)
plt.show()barplot의 top20
모델 Save & Read
import pickle
모델 저장
saved_model = pickle.dumps(model)
pickle 명령어
모델 Read
model_from_pickle = pickle.loads(saved_model)
상관계수 값 출력
import scipy.stats as stats
stats.pearsonr(x=df['x'], y=df['y'])
Regressor(회귀) 모델 학습 및 평가
모델링을 학습하기 위한 Fearue(X)와 Y데이터를 구분하는 단계
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestRegressor
from sklearn import metrics
X=df.drop(['y'], axis=1)
Y=df['y']
x_train, x_test, y_train, y_test = train_test_split(X, Y, test_size=0.3)
print(x_train.shape)
print(y_train.shape)
print(x_test.shape)
print(y_test.shape)
RandomForestRegressor 모델 학습
rfr = RandomForestRegressor()
rfr.fit(x_train, y_train)
예측
예측은 학습에 사용된 Data와 Test Data 모두 예측하고 평가함(※ 과적합 여부 판별)
import numpy as np
from sklearn.metrics import mean_absolute_error, r2_score
y_pred_train = rfr.predict(x_train)
y_pred_test = rfr.predict(x_test)
mse_train = mean_absolute_error(y_train, y_pred_train)
print('mse_train(mse): ', mse_train)
rmse_train = (np.sqrt(mse_train))
print('rmse_train(rmse): ', rmse_train)
r2_train = r2_score(y_train, y_pred_train)
print('rmse_train(r2): ', r2_train)
print('')
mse_test = mean_absolute_error(y_test, y_pred_test)
print('mse_test(mse): ', mse_test)
rmse_test = (np.sqrt(mse_test))
print('rmse_test(rmse): ', rmse_test)
r2_test = r2_score(y_test, y_pred_test)
print('rmse_test(r2): ', r2_test)이진분류와 회귀 모델은 성능, 오차 평가 방법 다름
표준화 및 PCA 차원축소
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
x = StandardScaler().fit_transform(x)
pca = PCA(n_components = 2)
principalComponents = pca.fit_transform(x)
principalDf = pd.DataFrame(data = principalComponents
, columns = ['principal component 1', 'principal component 2'])
선형회귀활용 모델링
모델링을 학습하기 위한 Fearue(X)와 Y데이터를 구분하는 단계
from sklearn.model_selection import train_test_split
from sklearn import metrics
X=df.drop(['y'], axis=1)
Y=df['y']
x_train, x_test, y_train, y_test = train_test_split(X, Y, test_size=0.3)
print(x_train.shape)
print(y_train.shape)
print(x_test.shape)
print(y_test.shape)
LR(선형회귀) 모델 활용
from sklearn.linear_model import LinearRegression
mlr = LinearRegression()
mlr.fit(x_train, y_train)
예측
예측은 학습에 사용된 Data와 Test Data 모두 예측하고 평가함(※ 과적합 여부 판별)
import numpy as np
from sklearn.metrics import mean_absolute_error, r2_score
y_pred_train = mlr.predict(x_train)
y_pred_test = mlr.predict(x_test)
평가
mse_train = mean_absolute_error(y_train, y_pred_train)
print('mse_train(mse): ', mse_train)
rmse_train = (np.sqrt(mse_train))
print('rmse_train(rmse): ', rmse_train)
r2_train = r2_score(y_train, y_pred_train)
print('rmse_train(r2): ', r2_train)
print('')
mse_test = mean_absolute_error(y_test, y_pred_test)
print('mse_test(mse): ', mse_test)
rmse_test = (np.sqrt(mse_test))
print('rmse_test(rmse): ', rmse_test)
r2_test = r2_score(y_test, y_pred_test)
print('rmse_test(r2): ', r2_test)
선형회귀 상관계수 확인
dfcoef = pd.DataFrame({'col':X.columns, 'coef':mlr.coef}).reset_index(drop=True)
df_coef회귀계수는 featureimportance와 같은 각 변수에 대한 중요도를 뽑을 수 있다 coef라는 명령어를 통해
light gbm 활용 모델링
모델링을 학습하기 위한 Fearue(X)와 Y데이터를 구분하는 단계
import lightgbm as lgb
import numpy as np
from sklearn.model_selection import train_test_split
데이터 세트로드
X = df.drop(['y'], axis=1)
Y = df['y']
train/test split
x_train, x_test, y_train, y_test = train_test_split (X, Y, test_size = 0.3)
데이터 세트를 적절한 LGB 형식으로 변환
d_train = lgb.Dataset (x_train, label = y_train)
setting the parameters
params = {}
params [ 'learning_rate'] = 0.02
params [ 'boosting_type'] = 'gbdt’
params['objective'] = 'binary’
params [ 'metric' ] = 'binary_logloss’
params [ 'max_depth'] = 5
params [ 'num_leaves' ] = 32
params ['seed'] = 23456gbdt = GradientBoostingDecisionTree
binary_logloss = metric for binary-class
모델 학습
clf = lgb.train (params, d_train, 1000)
epocs에서 모델 훈련
보통 예측할 때 모델은 1이나 0으로 환산하는데 lgb모델은 예측확률로 뱉어준다
그래서 다시 1과 0으로 바꿔주는 작업 필요 (threshold 설정해 데이터 형태 변환한다고 말한다)
from sklearn.metrics import classification_report
y_pred_train = clf.predict(x_train)
for i in range(0,len(y_pred_train)):
if y_pred_train[i]>=.5:
y_pred_train[i]=1
else:
y_pred_train[i]=0setting threshold to .5
y_pred_test = clf.predict(x_test)
for i in range(0,len(y_pred_test)):
if y_pred_test[i]>=.5:
y_pred_test[i]=1
else:
y_pred_test[i]=0setting threshold to .5
print(classification_report(y_train, y_pred_train))
print(classification_report(y_test, y_pred_test))
연속형, 범주형 변수 list 나누기
import numpy as np
import pandas as pd
numeric, categorical value 나누기
numeric_list=[]
categoical_list=[]
for i in df.columns :
if df[i].dtypes == 'O' :
categoical_list.append(i)
else :
numeric_list.append(i)dtypes이라는 명령어는 데이터 타입을 뱉어준다
O는 object 타입
AUROC score 출력하기
from sklearn.metrics import roc_auc_score
y_pred_train_proba = rfc.predict_proba(x_train)[:, 1]
y_pred_test_proba = rfc.predict_proba(x_test)[:, 1]predict_proba라는 예측확률을 뱉는 명령어
여기선 1일 확률을 예측한다고 명시됨
roc_score_train = roc_auc_score(y_train, y_pred_train_proba)
roc_score_test = roc_auc_score(y_test, y_pred_test_proba)
print("roc_score_train :", roc_score_train)
print("roc_score_test :", roc_score_test)
Lable encoder 활용 범주형 데이터 처리
문자열 변수는 모델링에 바로 넣을 수 없기 때문에 encoding필요
from sklearn.preprocessing import LabelEncoder
for col in categoical_list:
print(col)
le = LabelEncoder()
le.fit(list(x_train[col].values) + list(x_test[col].values))
x_train[col] = le.transform(x_train[col])
x_test[col] = le.transform(x_test[col])인코딩도 모델이기 때문에 le라는 빈껍데기 만들어준다
ROC 커브 그리기
from sklearn.metrics import roc_curve
def roc_curve_plot(y_test , pred_proba_c1):
fprs , tprs , thresholds = roc_curve(y_test ,pred_proba_c1)임곗값에 따른 FPR, TPR 값을 반환 받음.
FPR : 암환자가 아닌 환자를 암환자라고 잘 못 예측한 비율
TPR : Recall
plt.plot(fprs , tprs, label='ROC')
plt.plot([0, 1], [0, 1], 'k--', label='Random', color='red')ROC Curve를 plot 곡선으로 그림.
가운데 대각선 직선을 그림.
start, end = plt.xlim()
plt.xticks(np.round(np.arange(start, end, 0.1),2))
plt.xlim(0,1)
plt.ylim(0,1)
plt.xlabel('FPR( 1 - Sensitivity )')
plt.ylabel('TPR( Recall )')
plt.legend()
plt.show()FPR X 축의 Scale을 0.1 단위로 변경, X,Y 축명 설정등
roc_curve_plot(y_test, y_pred_test_proba)
min-max scale 활용 정규화
from sklearn.preprocessing import minmax_scale
rfm['Recency'] = minmax_scale(rfm['Recency'], axis=0, copy=True)minmax_scale은 데이터를 0~1 사이에 두는 명령어
"이 글은 제로베이스 데이터 분석 취업 스쿨의 강의 자료 일부를 발췌하여 작성되었습니다."