본문 바로가기

Computer Science/파이썬

[Python] 데이터 전처리 1 - 결측치 확인 및 처리

데이터를 불러왔으면 이제부터 데이터 전처리 과정이 시작된다, 데이터의 구성요소를 빠르게 확인하고 제대로된 데이터들로 만들어 줘야 한다. 

  1. 데이터 확인
    1. df.shape() ==> 데이터셋의 형태, 즉 열과 행의 수를 보여줌 
    2. df.head() / df.tail() ==> 데이터셋의 위에서 5개 / 아래서 5개 보여줌 (괄호안에 int를 넣으면 그 int만큼 보여줌)
    3. dtypes ==> 데이터 프레임의 type을 보여줌 (float, object, str...etc.)
    4. df.describe() ==> 데이터셋의 numeric 행에 대한 count, mean, std(표준편차), min, 25%(Q1), 50%(Q2), 75%(Q3), max(Q4)값을 한번에 보여줌
  2. 결측치 확인
    1. df.info() ==> 데이터셋의 행, 열의 수와  전체 dtypes 그리고 결측치를 한번에 보여줌
    2. df.isnull() => null 값을 True / False 로 나타낸다. /(반대 df.notull()   
      df.loc[df['원하는 컬럼의 명'].isnull()] ==> 원하는 컬럼의 결측치만 모아서 보여준다.
      [in]
      df.loc[df['F2'].isnull()]​
      
      
      [out]
      	F1	F2	F3	F4		F5		F6	F7	F8	F9
      20	N	NaN	A	1.928164	0.222397	G	6.0	Y	N
      54	N	NaN	b	3.311876	0.036056	G	4.0	Z	N
      85	N	NaN	B	3.705537	0.036873	H	4.0	X	N
      96	N	NaN	b	2.196954	0.373770	G	6.0	X	Y
      109	N	NaN	C	3.376163	0.428907	F	5.0	X	Y
      140	N	NaN	c	3.773357	0.825418	G	3.0	X	N
      143	N	NaN	C	2.472788	0.544661	H	3.0	Z	N
      153	N	NaN	D	3.478428	0.412326	G	6.0	Y	N
      191	D	NaN	D	2.467199	0.065689	H	8.0	Z	Y
    3. df.isnull().sum()  ==> True값(Null값)의 합을 나타낸다.  / (반대 df.notull().sum()
      sum() 괄호 안에 int 넣으면 그 row 단위로 결측값의 개수를 구할 수 있다. 
  3. 결측값 기본 처리
    1. 제거
      1. df.dropna()   >>> 결측값있는 row(axis=0, 기본값임) 전체 삭제
      2. df.dropna(axis=1)   >>> 결측값있는 column(axis=1)전체 삭제
      3. df[['여러개','컬럼은','대괄호두개']].dropna(axis=1) 
        >>> 특정 column을 대상으로 결측값이 있으면 해당 columns 전체 제거 (기본값은 axis=0, row제거됨)
      4. df.dropna(subset=['원하는행']) >>>> 원하는 행의 결측값이 있는 부분을 기준으로 전체 데이터의 row제거됨
    2. 결측값을 특정 값으로 채우기
      1. df = df.fillna(0)
      2. df = df.fillna(원하는 int값)
      3. df = df.fillna('원하는str값')
    3. 결측값을 앞 방향 혹은 뒷 방향으로 채우기
      1. fillna(method='ffill' or 'pad') >>> 결측값을 앞방향의 값으로 채운다
      2. fillna(method='bfill' or 'backfill') >>> 결측값을 뒷방향의 값으로 채운다
      3. fillna(method='ffill', limit=원하는횟수의 숫자) >>> 원하는 회수만큼만 채우고 채우지 않는다. 
        [df]
        	C1        C2        C3
        0       NaN -0.228791 -0.850988
        1       NaN  0.564767       NaN
        2 -0.834515       NaN -0.566917
        3  0.242694       NaN -0.673298
        4 -0.497041 -0.301435       NaN
        
        [In] 
        
        df.fillna(method='ffill', limit=1) # fill values forward with limit
        
        [Out]
        
                 C1        C2        C3
        0       NaN -0.228791 -0.850988
        1       NaN  0.564767 -0.850988
        2 -0.834515  0.564767 -0.566917
        3  0.242694       NaN -0.673298
        4 -0.497041 -0.301435 -0.673298
        
    4. 결측값을 변수별 평균으로 대체하기
      1. df.fillna(df.mean())
        >> 각 컬럼의 평균값으로 해당 컬럼의 null값이 채워진다.
      2. df.fillna(df.mean()['원하는컬럼의이름'])
        >> 원하는 컬럼의 평균 1의 값으로 모든 컬럼의 null값이 채워짐
      3. df.fillna(df.mea()['시작컬럼':'범위끝나는컬럼명'])
        >> 원하는 범위의 컬럼의 null값이 선택된 범위의 각 컬럼 평균으로 그 컬럼들만 채워짐
    5. 결측값을 다른 변수의 값으로 대체하기
      1. np.where(pd.notnull(df['null값보유컬럼']==True, df['null값보유컬럼],df['null값없는컬럼'])
        >> null 값을 보유하고 있는 컬럼에 결측값이 있는 행의 값을 null값이 없는 컬럼, 즉 채우고싶은 값이 있는 컬럼의 같은 row의 값을 가져와 채운다.
        [In] 
        df_2['C2_New'] = np.where(pd.notnull(df_2['C2']) == True, df_2['C2'], df_2['C1'])
        df_2
        
        [Out]
           C1    C2    C2_New
        0   1   6.0     6.0
        1   2   NaN     2.0
        2   3   8.0     8.0
        3   4   NaN     4.0
        4   5  10.0     10.0

      2. df.replace(이전값, 바꿀값)
        list_df.replace(np.nan, 5) >> 결측값을 5로 변경

        df.replace({'원하는 column 명' : 바꾸고싶은값}, {'원하는 column 명' : 새로운값})
  4. 결측값 특수 처리
    1.  결측값을 선형으로 비례하는 방식으로 결측값 보간 =적절한 비율의 값으로 보간
      1. df.interpolate(method = 'values) >>> (기본값 : method = 'values')
      2. df.interpolate(limit=1) >> 하나의 컬럼에 1개의 결측값만 채워진다, 보간 개수가 제한됨. limit direction 값을 추가하면 'bacward', 'forward'(기본값),'both' 로 방향 설정 가능함
    2. 결측값을 그룹화한 특정값으로 채우기
      1. 그룹화한 평균값으로 채우기
        >>> 우선 그룹화 시켜 값을 확인하고, lambda함수를 만든후 apply 시킨다.
        # 값확인용
        df.groupby('그룹하고싶은컬럼').mean()
        
        #  lambda 함수 만들고 apply
        fill_mean_func = lambda x: x.fillna(x.mean())
        df.groupby('그룹하고싶은컬럼').apply(fill_mean_func)

      2. 그룹별 특정 값을 적용하기
        >>> 우선 특정값을 지정하고, lambda 함수를 만든후 apply
        # 특정값 지정은 dict형식으로 한다 그룹화 한 값 'a', 'b'의 그룹에 채울 새로운값 지정
        fill_values = {'a': 1.0, 'b':0.5} 
        
        # lambda 함수 지정
        fill_func = lambda x: x.fillna(fill_values[x.name])
        df.group('그룹화할col명').apply(fill_func)