ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • <TIL> 2024-02-07
    내일배움캠프(데이터 분석 부트캠프 1기)/TIL & WIL 2024. 2. 7. 22:05
    • 오늘 진행한 일 
      • 팀 프로젝트 데이터 탐색적 분석
      • 팀 프로젝트 데이터 전처리 및 튜터링 준비

    https://www.kaggle.com/datasets/dev7halo/wine-information

     

    Wine Information

    Wine Information with nation, varieties, flavor, price, etc

    www.kaggle.com

     

    팀 프로젝트용 와인 데이터를 받았는데 데이터의 전처리에 상당히 공을 들여야할 것 같은 데이터였다. 

     

    오늘은 그래서 데이터를 EDA하고 전처리를 하는데 대부분의 시간을 할애하였다. 

    자세한 EDA와 전처리 내용은 전처리가 정해지고 프로젝트가 어느정도 마무리가 되었을 때 따로 팀프로젝트 카테고리에 글로 남기려고 한다. 

    import pandas as pd
    import numpy as np
    import matplotlib.pyplot as plt
    import seaborn as sns
    
    cleansingWine = pd.read_csv('./data/wine/cleansingWine.csv', encoding='utf-8').drop('Unnamed: 0', axis=1)
    cleansingWine

    cleansingWine.isnull().sum()

     

    결측치를 확인해본 결과 전체 데이터 21605행 중에 상당수가 결측치인 데이터들도 꽤 있었다. 

    와인의 생산지역을 의미하는 local 데이터의경우 2~4는 절반 이상 결측치여서 삭제하기로 했다.

    그리고 와인의 품종을 의미하는 varieties의 경우에도 2~12는 절반이상 결측치여서 삭제 조치했다. 

    그리고 와인의 이름(name)의 경우 학습에 영향을 줄 수 있는 데이터가 아니기 때문에 없앴고

    와인 생산자(producer)의 경우 unique()값이 4089개여서 사용하지 않기로 했다. 


    print(wine['use'].unique())
    ['Table' 'Dessert' 'Table, Dessert' 'Appetizer' 'Appetizer, Table'
     'Appetizer, Dessert' 'Appetizer, Table, Dessert' 'Etc'
     'Appetizer, Table, Etc' 'Appetizer, Etc' 'Dessert, Etc' nan 'Table, Etc']

     

    그 외에 와인의 용도(use)의 경우 다중값 속성으로 이루어져있어 이를 원핫 인코딩을 해주고자 했는데 단순히 pd.get_dummies를 하면 Table과 Table Dessert가 별개의 변수가 될 것이라 의미가 없어진다고 생각했다. 


    wine['use_Table'] = np.NaN
    wine['use_Dessert'] = np.NaN
    wine['use_Appetizer'] = np.NaN
    wine['use_Etc'] = np.NaN
    
    def use_onehot(df:pd.DataFrame, columns:list, attribute:list) : 
        for col, attri in zip(columns, attribute) : 
            for i in range(df.shape[0]) : 
                if pd.isna(df['use'][i]) : 
                    pass
                elif (attri in df['use'][i]) : 
                    df[col][i] = 1
                else : 
                    df[col][i] = 0
               
    use_columns = ['use_Table', 'use_Dessert', 'use_Appetizer', 'use_Etc']
    use_attribute = ['Table', 'Dessert', 'Appetizer', 'Etc']
    
    use_onehot(wine, use_columns, use_attribute)

     

    따라서 해당 속성을 포함하고 있다면 1이되는use_Table, use_Dessert, use_Appetizer, use_Etc 컬럼을 생성하였다.

    생성 방법은 우선 NaN으로 먼저 해당 칼럼을 채운 뒤 for문으로 행을 일일히 조회하여 해당하는 값이 존재한다면 대응하는 새로운 컬럼에 값을 1로 만들어주고 없다면 0으로 만들어주는 방식으로 하였다

     

    이를 위해 이중  for문으로 함수를 만들었다. 


    그리고 알코올 도수(abv)와 음용 온도(degree) 데이터의 경우 "14~15" 이런식으로 구간으로 적힌 string 데이터인 것을 알 수 있었다. 모든 값이 그렇게 적힌 것은 아니고 또 단일 값인 데이터도 섞여 있어서 이를 고려하여 함수를 작성해야했다.

    # abv, degree -> numeric
    
    def mean_range(x) :
        if pd.isna(x) : 
            return np.NaN
        elif x.find('~') != -1 : 
            num_list = x.split('~')
            return (float(num_list[0]) + float(num_list[1]))/2
        else : 
            return float(x)
        
    wine['abv'] = wine['abv'].apply(mean_range)
    wine['degree'] = wine['degree'].apply(mean_range)

     

    apply()를 사용하기 위해서 return 값을 주는 방식으로 함수를 작성하였고 ~가 있으면, 없으면을 조건으로 하여 값을 전처리 해주었다. 구간으로 되어 있는 데이터의 경우 두 값의 평균 값을 입력해주었다. 


     

    그리고 다른 범주형 변수들에 대해서도 레이블 인코딩으로 수치화 해주었다. 

    이렇게 범주형 변수를 수치화한 이유는 결측치를 보간해주기 위함인데 현재는 

    결측치 보간을 어떤 방식으로 진행할 지에 대해서 고민하고 있다. 

     

    단순대치법(평균, 중앙값, 최빈값)으로 대체하는 방법도 있겠고

    MICE방법을 이용한 결측치 보간법이나 머신러닝을 통한 결측치 보간 방법도 있다. 

    이를 혼용해서 사용할 수도 있는데 명확한 기준같은게 있는게 아니라 우선 튜터님께 내일 오전에 질문을 드려보려고한다. 

     

    결측치에 대한 부분은 따로 블로그에 작성하려고한다. 

    연휴 전날까지 빡세게 학습하고 연휴에는 좀 쉬어야지.

    '내일배움캠프(데이터 분석 부트캠프 1기) > TIL & WIL' 카테고리의 다른 글

    <WIL> 2024년 2월 2주차 회고  (0) 2024.02.08
    <TIL> 2024-02-08  (0) 2024.02.08
    <TIL> 2024-02-06  (0) 2024.02.06
    <TIL> 2024-02-05  (1) 2024.02.06
    <TIL> 2024-02-02  (0) 2024.02.02
Designed by Tistory.