데이터분석취업스쿨 스터디노트 - (4주차-1 파이썬 기초 챕터01 ~ 25)

서보석·2024년 11월 30일
0

교육

제로베이스_데이터분석취업스쿨

강의

파이썬 기초 챕터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, 경영정보시각화 등 데이터 자격증 공부를 할 때 배운 개념들과 큰 연관이 있었다.
파이썬은 데이터분석뿐만 아니라 데이터를 시각화하고 예측 모델을 형성하는 등 무척 다양한 업무를 수행할 수 있다고 느꼈다. 따라서 앞으로 프로젝트를 진행하거나 회사 생활을 할 때 핵심 중의 핵심 역량으로 생각이 들었다.
파이썬은 기본적으로 다양한 명령어가 마치 대화하듯 느껴졌다. 따라서 영어나 불어처럼 새로운 언어를 익힌다는 관점에서 접근해야할 것 같다. 즉, 끊임없이 복습하며 우선 친숙해질 예정이다. 그 후 제로베이스의 다양한 프로젝트를 진행하면서 실제로 직접 사용하는 것이 무척 중요할 것으로 보인다.

수업 내용

챕터 01. Getting & Knowing Data

  • Getting & Knowing Data
    • 가장 먼저 진행하는 단계이다. 데이터 읽고, 기본적인 정보들을 확인하고 특정 위치 데이터 파악

    • 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()

챕터 02. Filtering & Sorting

  • Filtering & Sorting
    • 필터링 : 원하는 데이터를 필터링 해서 보겠다

    • 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)) 와 함께 쓰니 한 줄로도 출력

챕터 03. Grouping

  • Grouping
    • 그룹을 지어 특정 관점, 기준으로 데이터를 보는 의미

    • 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은 행과 열의 차원을 변경

챕터 04. Apply, Map

  • Apply, Map
    • 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_Category

      df의 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로 표시 됨

챕터 05. Time_Series

  • Time_Series
    • 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 datetime

      change_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 옵션은 반영된 값을 원본데이터에 바로 반영하겠다는 의미

챕터 06. Pivot

  • Pitvot
    • 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을 사용할지 유의

챕터 07. Merge, Concat

  • Merge, Concat
    • 데이터 병합, 조인 기능

    • 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)

챕터 08. Statistics

  • Staticstics
    • 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()

챕터 09. Series & DataFrame

  • Series & DataFrame
    • 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값 선언

챕터 10. Visualization

  • Visualization
    • 시각화에 자주 사용되는 패키지

      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()

챕터 11. Deleting

  • Deleting
    • 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)

챕터 12. 실습

  • 실습
    • 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()

챕터 13. Python Cheat Sheet (실무필수문법)

  • Data Handling
    • 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 GridSearchCV

      GridSearchCV가 대표적 튜닝 방법

      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'] = 23456

      gbdt = 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]=0

      setting 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]=0

      setting 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 사이에 두는 명령어

    "이 글은 제로베이스 데이터 분석 취업 스쿨의 강의 자료 일부를 발췌하여 작성되었습니다."
profile
안녕하세요

0개의 댓글