Development Project

[ 2021 NIPA AI - 기본 ] 3. 공공데이터를 활용한 파이썬 데이터분석 프로젝트 - 3. 자동차 리콜 현황 데이터를 활용한 데이터 분석 본문

AI/Edu

[ 2021 NIPA AI - 기본 ] 3. 공공데이터를 활용한 파이썬 데이터분석 프로젝트 - 3. 자동차 리콜 현황 데이터를 활용한 데이터 분석

나를 위한 시간 2021. 12. 16. 19:59

=> 한국교통안전공단에서 제공한 2020년 자동차 결함 리콜 데이터를 활용하여 유의미한 패턴 및 인사이트를 발굴하고 시각화하는 실습

데이터 출처 : https://www.data.go.kr/data/3048950/fileData.do

 

한국교통안전공단_자동차결함 리콜현황_20201231

자동차의 리콜현황에 대한 데이터로 제작자, 차명, 생산기간(From), 생산기간(To) 리콜사유 등의 항목을 제공합니다.

www.data.go.kr

 

[Project 3] 자동차 리콜 데이터 분석

  1. 데이터 읽기
    1. 데이터 불러오기
      • import
        • import numpy as np 
          import pandas as pd 
          import matplotlib.pyplot as plt
          !pip install seaborn==0.9.0
          import seaborn as sns
          print(sns.__version__)
          # missingno라는 라이브러리가 설치되어 있을 경우 import
          try: 
              import missingno as msno
          # missingno라는 라이브러리가 설치되어 있지 않을 경우 설치 후 import
          except: 
              !pip install missingno
              import missingno as msno
      • 불러오기 [ read_csv("경로") ]
        • # pd.read_csv를 통하여 dataframe 형태로 읽어옵니다.
          df = pd.read_csv("./data/한국교통안전공단_자동차결함 리콜현황_20201231.csv", encoding="euc-kr")
      • 정보 출력 [ .head() / .info() ]
        • df.head()
        • df.head(10)
        • df.tail()
        • df.info()
    2. 데이터 정제
      1. 결측치 확인
        • import matplotlib.font_manager as fm
          
          font_dirs = ['/usr/share/fonts/truetype/nanum', ]
          font_files = fm.findSystemFonts(fontpaths=font_dirs)
          
          for font_file in font_files:
          	fm.fontManager.addfont(font_file)
          
          sns.set(font="NanumBarunGothic", 
          	rc={"axes.unicode_minus":False})
          msno.matrix(df)
          plt.show()
        • df.isna().sum()
      2. 중복값 확인
        • df[df.duplicated(keep=False)]
        • print("Before:", len(df))
          df = df.drop_duplicates()
          print("After:", len(df))
      3. 기초적인 데이터 변형
        • def parse_year(s):
              return int(s[:4])
          def parse_month(s):
              return int(s[5:7])
          def parse_day(s):
              return int(s[8:])
          
          # Pandas DataFrame에서는 row별로 loop를 도는 것이 굉장히 느리기 때문에, apply() 함수를 이용하여 벡터 연산을 진행합니다.
          df['start_year'] = df['생산기간'].apply(parse_year)
          df['start_month'] = df['생산기간'].apply(parse_month)
          df['start_day'] = df['생산기간'].apply(parse_day)
          
          df['end_year'] = df['생산기간.1'].apply(parse_year)
          df['end_month'] = df['생산기간.1'].apply(parse_month)
          df['end_day'] = df['생산기간.1'].apply(parse_day)
          
          df['recall_year'] = df['리콜개시일'].apply(parse_year)
          df['recall_month'] = df['리콜개시일'].apply(parse_month)
          df['recall_day'] = df['리콜개시일'].apply(parse_day)
          
          df.head(3)
        • # 불필요한 열은 버리고, 열 이름을 재정의합니다.
          df = df.drop(columns=['생산기간', '생산기간.1', '리콜개시일']).rename(columns={'제작자': "manufacturer", "차명": "model", "리콜사유": "cause"})
          df.head(3)
        • # 2019년의 데이터가 함께 존재함을 알 수 있습니다.
          df.recall_year.min(), df.recall_year.max()​
        • # 2020년의 데이터만을 남겨줍니다.
          df = df[df['recall_year']==2020]
          len(df)
    3. 데이터 시각화
      1. 제조사별 리콜 현황 출력
        • df.groupby("manufacturer").count()["model"].sort_values(ascending=False)
        • pd.DataFrame(df.groupby("manufacturer").count()["model"].sort_values(ascending=False)).rename(columns={"model": "count"})
        • tmp = pd.DataFrame(df.groupby("manufacturer").count()["model"].sort_values(ascending=False)).rename(columns={"model": "count"})
          plt.figure(figsize=(20,10))
          # 한글 출력을 위해서 폰트 옵션을 설정합니다.
          sns.set(font="NanumBarunGothic", 
                  rc={"axes.unicode_minus":False},
                  style='darkgrid')
          ax = sns.countplot(x="manufacturer", data=df, palette="Set2", order=tmp.index)
          plt.xticks(rotation=270)
          plt.show()
        • tmp.index
      2. 모델별 리콜 현황 출력
        • pd.DataFrame(df.groupby("model").count()["start_year"].sort_values(ascending=False)).rename(columns={"start_year": "count"}).head(10)
        • tmp = pd.DataFrame(df.groupby("model").count()["manufacturer"].sort_values(ascending=False))
          tmp = tmp.rename(columns={"manufacturer": "count"}).iloc[:50]
          
          # 그래프의 사이즈를 조절합니다.
          plt.figure(figsize=(10,5))
          
          # seaborn의 countplot 함수를 사용하여 출력합니다.
          sns.set(font="NanumBarunGothic", 
                  rc={"axes.unicode_minus":False},
                  style='darkgrid')
          ax = sns.countplot(x="model", data=df[df.model.isin(tmp.index)], palette="Set2", order=tmp.index)
          plt.xticks(rotation=270)
          plt.show()
        •  
      3. 월별 리콜 현황 출력
        • pd.DataFrame(df.groupby("recall_month").count()["start_year"].sort_values(ascending=False)).rename(columns={"start_year": "count"})
        • # 그래프의 사이즈를 조절합니다.
          plt.figure(figsize=(10,5))
          
          # seaborn의 countplot 함수를 사용하여 출력합니다.
          sns.set(style="darkgrid")
          ax = sns.countplot(x="recall_month", data=df, palette="Set2")
          plt.show()
      4. 생산연도별 리콜 현황 출력
        • tmp = pd.DataFrame(df.groupby("start_year").count()["model"]).rename(columns={"model": "count"}).reset_index()
          
          # 그래프의 사이즈를 조절합니다.
          plt.figure(figsize=(10,5))
          
          # seaborn의 countplot 함수를 사용하여 출력합니다.
          sns.set(style="darkgrid")
          sns.lineplot(data=tmp, x="start_year", y="count")
          plt.show()
        • tmp
      5. 4분기 제조사별 리콜 현황 출력
        • # 논리연산을 이용한 조건을 다음과 같이 사용하면 해당 조건에 맞는 데이터를 출력할 수 있습니다.
          df[df.recall_month.isin([10,11,12])].head()
        • # 그래프를 출력합니다.
          plt.figure(figsize=(20,10))
          sns.set(font="NanumBarunGothic", 
                  rc={"axes.unicode_minus":False},
                  style='darkgrid')
          ax = sns.countplot(x="manufacturer", data=df[df.recall_month.isin([10,11,12])], palette="Set2")
          plt.xticks(rotation=270)
          plt.show()
      6. 하반기 생산연도별 리콜 현황 출력
        • # 해당 column을 지정하여 series 형태로 출력할 수 있습니다.
          df[df.recall_month>=7].head()
        • # 그래프를 출력합니다.
          plt.figure(figsize=(10,5))
          sns.set(style="darkgrid")
          ax = sns.countplot(x="start_year", data=df[df.recall_month>=7], palette="Set2")
          plt.show()
      7. 워드 클라우드를 이용한 리콜 사유 시각화
        • # 워드 클라우드 생성을 도와주는 패키지를 가져옵니다.
          try:
              from wordcloud import WordCloud, STOPWORDS
          except:
              !pip install wordcloud
              from wordcloud import WordCloud, STOPWORDS
          # 문법적인 성분들을 배제하기 위해 stopwords들을 따로 저장해둡니다.
          set(STOPWORDS)
        • # 손으로 직접 리콜 사유와 관련이 적은 문법적 어구들을 배제해보겠습니다.
          spwords = set(["동안", "인하여", "있는", "경우", "있습니다", "가능성이", "않을", "차량의", "가", "에", "될", "이",
                         "인해", "수", "중", "시", "또는", "있음", "의", "및", "있으며", "발생할", "이로", "오류로", "해당"])
                         
          # 리콜 사유에 해당하는 열의 값들을 중복 제거한 뒤 모두 이어붙여서 text라는 문자열로 저장합니다.
          text = ""
          
          for c in df.cause.drop_duplicates():
              text += c
          
          text[:100]
        • # 한글을 사용하기 위해서는 폰트를 지정해주어야 합니다.
          wc1 = WordCloud(max_font_size=200, stopwords=spwords, font_path='/usr/share/fonts/truetype/nanum/NanumGothic.ttf',
                          background_color='white', width=800, height=800)
          wc1.generate(text)
          
          plt.figure(figsize=(10, 8))
          plt.imshow(wc1)
          plt.tight_layout(pad=0)
          plt.axis('off')
          plt.show()

 

Comments