ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 2. 판다스를 활용한 Null값 제거 (결측행, 결측열 제거)
    Data & ML & AI/Pandas & Scikit-Learn 2022. 5. 23. 21:37
    반응형

    stock_market.csv
    0.04MB

    지난번 다루었던 주식데이터, stock_market.csv의 몇 칼럼에서 결측값(null값, NaN)이 발견되었습니다.
    오늘은 결측값(missing value)들을 몇가지 방법으로 처리해 보겠습니다.

    결측값를 처리하는 방법은 크게 두가지로 나눌 수 있습니다.

    • 결측값 제거
    • 결측값 대체

    이 중, 먼저 결측값을 제거해보겠습니다.

    하지만 그 전에, 먼저 데이터를 살펴본 뒤에 결측치 처리 방향을 정해보겠습니다.

     

    1. 결측여부 확인

    먼저 지난번 사용했던 방법으로 다시 전체 칼럼의 상태를 살펴보겠습니다.

    # pandas
    import pandas as pd
    
    # data
    df = pd.read_csv('stock_market.csv')
    df.info()
    <class 'pandas.core.frame.DataFrame'>
    RangeIndex: 250 entries, 0 to 249
    Data columns (total 28 columns):
     #   Column                Non-Null Count  Dtype  
    ---  ------                --------------  -----  
     0   ID                    250 non-null    object 
     1   Name                  250 non-null    object 
     2   Market                250 non-null    object 
     3   Category              250 non-null    object 
     4   Capital               250 non-null    int64  
     5   PER                   249 non-null    float64
     6   EPS                   250 non-null    int64  
     7   ROE                   249 non-null    float64
     8   PBR                   250 non-null    float64
     9   BPS                   250 non-null    int64  
     10  Group_PER             250 non-null    float64
     11  Revenue               250 non-null    int64  
     12  Operating_Income      250 non-null    int64  
     13  Net_Income            250 non-null    int64  
     14  Dividend              189 non-null    float64
     15  Debt                  250 non-null    float64
     16  Debt_continuous       250 non-null    int64  
     17  Retention             250 non-null    float64
     18  Retention_Continuous  250 non-null    int64  
     19  Open                  250 non-null    int64  
     20  High                  250 non-null    int64  
     21  Low                   250 non-null    int64  
     22  Close                 250 non-null    int64  
     23  DaytoDay              250 non-null    int64  
     24  Volume                250 non-null    int64  
     25  Highest_Price         250 non-null    int64  
     26  Highest_Date          250 non-null    object 
     27  update_date           250 non-null    object 
    dtypes: float64(7), int64(15), object(6)
    memory usage: 54.8+ KB

    전체 행이 250개인 df에서 PER등이 일부 null값을 가지는 것을 확인할 수 있습니다.

    그리고 isnull()과 sum()을 함께쓰면 어느 칼럼에 몇개의 null이 있는지 좀 더 간단하게 볼 수 있습니다.

    df.isnull().sum()  # df.isna().sum()
    ID                       0
    Name                     0
    Market                   0
    Category                 0
    Capital                  0
    PER                      1
    EPS                      0
    ROE                      1
    PBR                      0
    BPS                      0
    Group_PER                0
    Revenue                  0
    Operating_Income         0
    Net_Income               0
    Dividend                61
    Debt                     0
    Debt_continuous          0
    Retention                0
    Retention_Continuous     0
    Open                     0
    High                     0
    Low                      0
    Close                    0
    DaytoDay                 0
    Volume                   0
    Highest_Price            0
    Highest_Date             0
    update_date              0
    dtype: int64

    칼럼이 너무 많아서 보기 불편하다면, null값이 있는 칼럼명만 뽑아 확인해 볼 수 있습니다.
    sum()대신 any()를 활용하면 됩니다.

    df.columns[df.isnull().any()]
    Index(['PER', 'ROE', 'Dividend'], dtype='object')

    칼럼이 너무 많아서 보기 힘드니 몇개만 골라서 사용해 보겠습니다.

    sample_df = df[['ID', 'Category', 'Name', 'PER', 'EPS', 'ROE', 'Dividend', 'Close']]
    sample_df.head(5)

    • PER : "주가수익비율"입니다. PER = 시가총액/순이익 = 주가/EPS
    • ROE : "자기자본수익률"입니다. ROE = 순이익/자기자본
    • Dividend : "배당"입니다. 단, 이 데이터에서는 '주당배당금(원)'대신 '시가배당률(%)'입니다.

     

    2. 결측값 제거

    결측값을 제거하는 방법은 또 크게 2가지로 나눌 수 있습니다.

    • 결측값이 있는 행(row)을 제거한다.
    • 결측값이 있는 열(column)을 제거한다.

    1) 결측값이 있는 행 일괄제거: dropna()

    dropna()로 결측값이 있는 행을 제거할 수 있습니다.

    del_row = sample_df.dropna()
    del_row

    다만 이 경우, 모든 칼럼에서 하나의 결측값이라도 있는 행은 모두 사라집니다.
    전체 250개 행밖에 되지 않는 작디작은 데이터였는데 그 중 거의 1/4가 사라져버렸군요.

    칼럼별로 다르게 대처할 필요가 있어보입니다.
    각각 결측값이 하나밖에 없는 PER, ROE칼럼에서만 결측값이 있는 행을 살펴보겠습니다.

    sample_df[sample_df['PER'].isnull() | sample_df['ROE'].isnull()]

    운이 좋은건지 나쁜건지 같은 행에서 결측이 발생했군요!&nbsp;행 하나만 제거하면 두 칼럼이 행복해질 것 같습니다.

    저 행을 직접 제거해도 되겠지만 '결측값처리'라는 주제에 맞게 dropna()를 이용하려고 합니다.

    결측값을 탐색하려는 칼럼들만 subset으로 지정해서 사용하면 해결입니다.

     

    2) 특정 칼럼에서만 결측값이 있는 행 제거

    del_row = sample_df.dropna(subset=['PER','ROE'])
    del_row

    행 개수가 250개에서 249개로 줄었습니다.

     

    3) 결측값이 있는 열 제거: dropna(axis=1)

    결측치를 가진 행이 너무 많은 경우, 차라리 결측이 많이 발생하는 열을 제거할 수도 있을 겁니다.

    del_col = sample_df.dropna(axis=1)
    del_col

    칼럼 개수가 8개에서 5개로 줄었습니다.

    결측치가 하나라도 있는 PER, ROE, Dividend 칼럼이 사라졌습니다.

     

    4) 특정 열 제거: drop(axis=1)

    어떤 열을 제거해야할 지 명확히 알고있다면 직접 칼럼명을 지정해서 제거할 수도 있습니다.

    여기서는 유독 결측치가 많은 Dividend만을 제거해보겠습니다.

    del_col = sample_df.drop(['Dividend'], axis=1)
    del_col

    칼럼 개수가 8개에서 7개가 되었습니다.

    Null값을  제거하는 것은 매우 간단한 일이지만 주의를 요하는 일입니다.

    그래서 다음번에는 결측치를 제거하는 것 대신, 빈 자리에 다른 값을 채워넣는 방법을 실습해 보겠습니다.

    반응형

    댓글

Designed by Tistory.