본문 바로가기
python/Pandas

Pandas - Null Data 처리방법 ( ffill, bfill, mean, interpolate 차이 그래프 비교 )

by 맑은안개 2021. 3. 5.

머신러닝, 빅데이터 사용에 있어 데이터 전처리 과정은 필수 과정이다.

누락된 데이터는 없는지 데이터는 어떤 형태로 존재하고 있는지 면밀히 확인해야 `처리` 과정에서 문제를 사전에 차단할 수 있다.

Null 처리는 전처리 과정에서 무엇보다 중요하다. Pandas 에서 null 데이터를 어떻게 처리하는지 알아보도록 한다.


Pandas에서 처리하는 Null 데이터

  - numpy.NaN, numpy.NaT, None

 

Pandas에서는 numpy.inf ( infinity ), '' (empty string)은 Null이 아닌것으로 취급한다.


개발 환경

- Python 3.9

- Pandas 1.2.0

 

테스트 DataFrame 준비

df = pd.DataFrame(dict(age=[np.NaN, np.NaN, 6],
                   born=[pd.NaT, pd.Timestamp('1939-05-27'),
                         pd.Timestamp('1940-04-25')],
                   name=[np.NaN, 'Batman', ''],
                   toy=[None, 'Batmobile', 'Joker']))

info()

DataFrame의 info함수는 데이터의 개략적인 정보를 파악하는데 유용하다.

non-null count 는 null 이 아닌 데이터의 총계이다.

df.info(null_counts=True)

# OUTPUT
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 3 entries, 0 to 2
Data columns (total 4 columns):
 #   Column  Non-Null Count  Dtype         
---  ------  --------------  -----         
 0   age     1 non-null      float64       
 1   born    2 non-null      datetime64[ns]
 2   name    2 non-null      object        
 3   toy     2 non-null      object        
dtypes: datetime64[ns](1), float64(1), object(2)
memory usage: 224.0+ bytes

 

isna()

- null인 데이터는 True, 아니면 False를 반환한다. ( isnull과 동일 )

df[df.age.isna()]

# OUTPUT
	age	born	name	toy
1	NaN	1939-05-27	Batman	Batmobile

 

notna()

- null이 아닌 데이터는 True, 아니면 False를 반환한다.

df[df.age.notna()]

# OUTPUT
	age	born	name	toy
0	5.0	NaT	Alfred	None
2	6.0	1940-04-25		Joker

 

dropna()

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

- null이 존재하는 데이터를 삭제한다.

# 1
df.dropna()

# OUTPUT
	age	born	name	toy
2	6.0	1940-04-25		Joker

# 2
df.dropna(subset=['age']) # age가 null인 데이터를 모두 지운다.

# OUTPUT
	age	born	name	toy
0	5.0	NaT	Alfred	None
2	6.0	1940-04-25		Joker

# 3
df.dropna(axis=1) # 컬럼(axis=1) 기준으로 null이 포함된 데이터를 모두 지운다.

#OUTPUT
	name
0	Alfred
1	Batman
2	

# 4
df.dropna(inplace=True) # 삭제된 DataFrame을 반환치 않고 바로 반영한다.

- how='all' 파라미터는 aixs 옵션에 따라 모든 row나 column이 null 일때 삭제한다.

 

삭제 후 인덱싱 재처리( reindex )

- 데이터 삭제 후 인덱싱을 재처리 해야 할 필요가 있다. 이때 reset_index 함수를 사용한다.

df[df.age.notna()].reset_index()

# OUTPUT 
	index	age	born	name	toy
0	0	5.0	NaT	Alfred	None
1	2	6.0	1940-04-25		Joker

- 파라미터로 drop=True를 전달하게 되면 기존 index를 갖고 있는 index 컬럼을 지운다.

df[df.age.notna()].reset_index(drop=True)

# OUTPUT
	age	born	name	toy
0	5.0	NaT	Alfred	None
1	6.0	1940-04-25		Joker

 

Null 데이터 변경

- fillna 함수를 사용하여 na 데이터를 변경할 수 있다.

df.age = df.age.fillna(0)
df

# OUTPUT
	age	born	name	toy
0	0.0	NaT	NaN	None
1	0.0	1939-05-27	Batman	Batmobile
2	6.0	1940-04-25		Joker

 - 파라미터 method='bfill' | 'ffill'을 사용하여 인덱스 상에 앞(ffill), 뒤(bfill) 데이터로 채운다.

df.fillna(method='bfill')

# OUTPUT
	age	born	name	toy
0	6.0	1939-05-27	Batman	Batmobile
1	6.0	1939-05-27	Batman	Batmobile
2	6.0	1940-04-25		Joker

 

시계열 자료의 Null 치환

- 시계열 데이터처럼 연속적인 특징을 갖는 컬럼 중 Null 이 존재할 때 어떻게 처리해야 할까 ? bfill, ffill ? zero ? 아니면 평균 ? 다음 그래프를 보고 판단해보자. ( matplotlib library가 설치 되어야 한다. )

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams["legend.loc"] = "upper center"

# 자료 초기화
y = pd.Series([1, 4, 2, 4, np.NaN, np.NaN, 7, 5, 4, np.NaN, np.NaN, 1, 2])
x = np.arange(0, len(y))

# 차트 생성
fig, ax = plt.subplots(nrows=1, ncols=4, figsize=(25,3))
ax[0].plot(x, y.fillna(0), color='red', label='updated')
ax[0].plot(x, y, label='original')
ax[0].set_title('zero')

ax[1].plot(x, y.fillna(y.mean()), color='red')
ax[1].plot(x, y)
ax[1].set_title('mean')

ax[2].plot(x, y.ffill(), color='red')
ax[2].plot(x, y)
ax[2].set_title('ffill')

ax[3].plot(x, y.interpolate(), color='red')
ax[3].plot(x, y)
ax[3].set_title('interpolate')

fig.legend()

- 중간중간에 데이터를 Null로 만든 샘플을 준비 했다. Null을 -0(zero), 평균(mean), ffill, 보간(interpolate)처리한 값은 빨간색 선분으로 표시했다.

zero, mean, ffill, interpolate 4가지 방법

- 보는것처럼 연속적인 값을 갖는 데이터는 보간처리( interpolate ), 평균( mean )처리 된 그래프가 적합하다. - 데이터 특징에 맞게 알맞은 치환방법을 선택한다.

반응형