Pandas DataFrame 결측제어

상후·2025년 4월 10일
post-thumbnail

시작하기 전에 import 하기

import numpy as np
import pandas as pd
import numba

결측값 확인 (isna, isnull, notna, notnull)

DataFrame.isna( )
isnull( )과 완전히 동일합니다.
DataFrame.notna( )
notnull( )과 완전히 동일합니다.

개요

isna 메서드와 notna 메서드는 DataFrame내의 결측값을 확인해서 bool형식으로 반환하는 메서드입니다.
isna의 경우 결측값이면 True 반환, 정상값이면 False반환이며,
notna의 경우 결측값이면False반환, 정상값이면 True를 반환합니다.

사용법

기본 사용법
df.isna( ) / df.notna( )
np.inf나 그냥 ' ' 의경우 결측값으로 판단하지 않습니다.

예시

먼저 다양한 결측값이 포함된 간단한 4x4짜리 데이터를 만들어보겠습니다.

col  = ['col1','col2','col3','col4']
row  = ['row1','row2','row3']
data = [[1,2,pd.NA,4],
        [np.nan,6,7,8],
        [9,10,11,None]]
df = pd.DataFrame(data,row,col)
print(df)

isna / isnull의 사용
isna나 isnull의 경우 결측값이면 True를 반환합니다.

print(df.isna())

notna / notnull의 사용
notna나 notnull의 경우 결측값이면 False를 반환합니다.

print(df.notna())


결측값 제거 (dropna)

DataFrame.dropna(axis=0, how='any', thresh=None, subset=None, inplace=False)

개요

dropna 메서드는 DataFramde내의 결측값이 포함된 레이블을 제거하는 메서드입니다.

사용법

기본 사용법
df.dropna(axis=0, how='any', thresh=None, subset=None, inplace=False)
axis : {0: index / 1: columns} 결측치 제거를 진행 할 레이블입니다.
how : {'any' : 존재하면 제거 / 'all' : 모두 결측치면 제거} 제거할 유형입니다. 포함만 시켜도 제거할지, 전무 NA여야 제거할지 정할 수 있습니다.
tresh : 결측값이 아닌 값이 몇 개 미만일 경우에만 적용시키는 인수 입니다.
예를들어, tresh값이 3이라면 결측값이 아닌 값이 3개 미만일 경우에만 dropna메서드를 수행합니다.
subset : dropna메서드를 수행할 레이블을 지정합니다.
inplace : 원본을 변경할지의 여부입니다.

예시

먼저 pd.NA가 포함된 간단한 4x5짜리 데이터를 만들어보겠습니다.

col  = ['col1','col2','col3','col4','col5']
row  = ['row1','row2','row3','row4']
data = [[1,2,3,pd.NA,5],[6,pd.NA,8,pd.NA,10],[11,12,13,14,15],[pd.NA,pd.NA,pd.NA,pd.NA,pd.NA]]
df = pd.DataFrame(data,row,col)
print(df)

axis값에 따른 결측치 제거 수행
axis가 0인경우 행에 대해서, axis가 1인경우 열에 대해서 결측치 제거가 수행됩니다.
axis=0인 경우 결측치가 포함된 모든 행이 제거되었습니다.

print(df.dropna(axis=0))

axis=1인 경우 결측치가 포함된 모든 열이 제거되었습니다. 예시의 경우 모든 열에 NA가 존재하므로 빈 값이 반환됩니다.

print(df.dropna(axis=1))

how로 연산기준을 정할 경우
기본적으로 how 는 'any'이며 이 경우 한 값이라도 NA를 가진다면 해당 레이블을 제거합니다.

print(df.dropna(how='any'))

how를 'all'로 할 경우 모든값이 NA인 레이블만 삭제됩니다.

print(df.dropna(how='all'))

thresh 를 이용하는 경우
thresh를 이용하여 정상값의 수를 보장할 수 있습니다.
thresh가 3일 경우 정상값이 3개 미만인 경우에 대해서만 결측치 보정을 진행합니다.

print(df.dropna(thresh=3))

thresh가 4인 경우 정상값이 4개 미만인 경우에 대해서 결측치 보정을 진행합니다.

print(df.dropna(thresh=4))

subset 인수를 통한 레이블 지정
subset에 리스트형태의 값을 입력함으로써 결측치 제거를 수행할 레이블을 지정할 수 있습니다.
col1, col2에 대해서 결측치가 있는경우만 제거되었습니다.

print(df.dropna(subset=['col1','col2']))

inplcae 인수를 통한 원본의 수정
Pandas에서 공통적으로 inplace 인수는 원본의 수정을 의미합니다. inplace가 True인 경우 원본이 수정됩니다.

df.dropna(inplace=True)
print(df)


결측값 없는 인덱스 확인 (first_valid_index / last_valid_index)

DataFrame.first_valid_index( )
DataFrame.last_valid_index( )

개요

first_valid_index메서드의 경우 처음으로 결측치가 아닌값이 나오는 행의 인덱스를 출력합니다.
last_valid_index메서드의 경우 마지막으로 결측치가 아닌값이 나오는 행의 인덱스를 출력합니다.
즉, 결측값만 있는 행은 무시한다고 생각하면 됩니다.

사용법

기본 사용법
df.first_valid_index( )
df.last_valid_index( )

예시

먼저 다양한 결측값이 포함된 간단한 5x2짜리 데이터를 만들어보겠습니다.

col  = ['col1','col2']
row  = ['row1','row2','row3','row4','row5']
data = [[np.nan,np.nan],[pd.NA,4],[pd.NA,pd.NaT],[5,6],[np.nan,pd.NA]]
df = pd.DataFrame(data,row,col)
print(df)

first_valid_index의 사용
first_valid_index메서드의 경우 처음으로 결측치가 아닌값이 나오는 행의 인덱스를 출력합니다.
이 경우 row2에서 처음으로 정상값인 4가 있으므로 row2를 출력합니다.

print(df.first_valid_index()) 

last_valid_index의 사용
last_valid_index메서드의 경우 마지막으로 결측치가 아닌값이 나오는 행의 인덱스를 출력합니다.
이 경우 row4이후에는 정상값이 없으므로 row4를 출력합니다.

print(df.last_valid_index())


결측값 변경 (fillna / backfill / bfill / pad / ffill)

DataFrame.fillna(value=None, method=None, axis=None, inplace=False, limit=None, downcast=None)
DataFrame.backfill( ) / DataFrame.bfill : DataFrame.fillna(mathod='bfill')과 동일합니다.
DataFrame.pad / DataFrame.ffill : DataFrame.fillna(method='ffill')과 동일합니다.

개요

fillna 메서드는 DataFrame에서 결측값을 원하는 값으로 변경하는 메서드입니다.

사용법

기본 사용법
df.fillna(value=None, method=None, axis=None, inplace=False, limit=None, downcast=None)
value : 결측값을 대체할 값입니다. dict형태로도 가능합니다.
method : 결측값을 변경할 방식입니다. bfill로 할경우 결측값을 바로 아래 값과 동일하게 변경합니다.
ffill로 할 경우 결측값을 바로 위 값과 동일하게 변경합니다.
axis : {0 : index / 1 : columns} fillna 메서드를 적용할 레이블입니다.
inplace : 원본을 변경할지 여부입니다. True일 경우 원본을 변경하게 됩니다.
limit : 결측값을 변경할 횟수입니다. 위에서부터 limit로 지정된 갯수만큼만 변경합니다.
downcast : 다운캐스트할지 여부입니다. downcast='infer'일 경우 float64를 int64로 변경합니다.

예시

먼저 다양한 결측값이 포함된 간단한 5x5짜리 데이터를 만들어보겠습니다.

col  = ['col1','col2','col3','col4','col5']
row  = ['row1','row2','row3','row4','row5']
na = np.nan
data = [[na, 2,na, 4,na],
        [ 6, 7,na, 9,na],
        [11,na,na,14,15],
        [na,17,na,na,20],
        [na,22,na,na,25]]
df = pd.DataFrame(data,row,col)
print(df)

value의 형식에 따른 사용
value가 숫자나 문자일 경우 그대로 결측값을 대체하게 됩니다. 여기서는 A로 바꿔보겠습니다.

print(df.fillna('A'))

dict형태로 입력할 경우 각각 레이블값에 대해 원하는 값으로의 변경이 가능합니다.

dict = {'col1':'A','col2':'B','col3':'C','col4':'D','col5':'E'}
print(df.fillna(value=dict))

method인수를 사용하는 경우
method인수에 bfill을 입력할 경우 결측값이 바로 아래값과 동일하게 설정됩니다.
df.backfill( )이나 df.bfill( )과 완전히 동일한 기능을 수행합니다.

print(df.fillna(method='bfill'))

method인수에 ffill을 입력할 경우 결측값이 바로 위값과 동일하게 설정됩니다.
df.pad( )나 df.ffill( )과 완전히 동일한 기능을 수행합니다.

print(df.fillna(method='ffill'))

limit인수를 사용하는 경우
limit인수는 각 레이블값에 대해서 결측치 변경을 수행할 횟수입니다. 행 기준일경우 왼쪽부터, 열 기준일 경우 위에서부터 수행합니다.

print(df.fillna('A', limit=2))

downcast인수를 사용하는 경우
downcast 인수를 'infer'로 설정함으로써 float64형태를 int64형태로 변경할 수 있습니다.

print(df.fillna(0, downcast='infer'))

inplace를 사용하는 경우
다른 파이썬 객체에서와 마찬가지로 inplace는 원본을 덮어씌우는 기능과 유사한 기능알 합니다.
즉 df.fillna(0, inplace=True) 는 df=df.fillna(0)과 동일한 기능을 합니다.

df.fillna('A',inplace=True)
print(df)


결측값 없는 마지막 행 반환 (asof)

DataFrame.asof(where, subset=None)

개요

asof 메서드는 인덱스 기준으로 where이전에 결측치가 없는 마지막 행을 구합니다.

사용법

기본 사용법
df.asof(where, subset=None)
where : 기준이 되는 인덱스 값입니다.
subset : 기준이 되는 열 입니다.

예시

먼저 결측치가 포함된 6x2짜리 객체를 생성해보겠습니다.

row = [10, 20, 30, 40, 50, 60]
data = {'A': [1, np.nan, np.nan, 4, 5, 6], 'B': [7, 8, 9, 10, np.nan, 12]}
df = pd.DataFrame(data=data, index=row)
print(df)

기본적인 사용법
where이 단일값이면 반환은 Series형태로 하게 됩니다. subset을 입력하지 않으면 모든 열에대해서 조건을 만족하는 경우를 반환합니다.

print(df.asof(where=45))


45이전에 A열과 B열 모두 결측치가 없는 행은 40입니다. Index가 40인 값을 출력하였습니다.

입력값이 list인 경우
입력값이 list인 경우 list의 각각 요소에 대해 조건을 만족하는 행을 DataFrame 형태로 반환합니다.

print(df.asof(where=[10,45,60]))


10이전에 A와 B모두 결측치가 없는 행은 10입니다.
45이전에 A와 B모두 결측치가 없는 행은 40입니다.
60이전에 A와 B모두 결측치가 없는 행은 60입니다.

subset의 사용
subset을 이용해 특정 열에 대해서만 만족하는 경우를 반환할 수 있습니다.
A에 대해서만 연산 할 경우

print(df.asof(where=[10,35,60],subset='A'))


10이전에 A에 대해서 결측치가 없는 행은 10입니다.
35이전에 A에 대해서 결측치가 없는 행은 10입니다.
60이전에 A에 대해서 결측치가 없는 행은 60입니다.

B에 대해서만 연산 할 경우

print(df.asof(where=[10,35,60],subset='B'))


profile
개발자를 꿈꾸는 학생

0개의 댓글