1. Handling Missing Data - isnull()
데이터를 분석할 때, 데이터가 누락되는 것은 매우 흔한 일입니다.
Pandas에서는 누락된 데이터를 처리하는 것이 간단하고, 편합니다.
우선 어떤 데이터가 누락되었는지 알려주는 isnull() 함수를 사용하겠습니다.
import pandas as pd
import numpy as np
string_data = pd.Series(['aardvark', 'artichoke', np.nan, 'avocado'])
string_data
0 aardvark
1 artichoke
2 NaN
3 avocado
dtype: object
string_data.isnull()
0 False
1 False
2 True
3 False
dtype: bool
만약 데이터를 바꾼다면,
string_data[0] = None
string_data.isnull()
0 True
1 False
2 True
3 False
dtype: bool
isnull()이 제대로 된 값을 출력합니다.
2. Filtering Out Missing Data - dropna()
누락된 데이터를 처리하는 여러 방법이 있지만, 제일 간단한 건 그냥 없애는 방법입니다.
from numpy import nan as NA
data = pd.Series([1, NA, 3.5, NA, 7])
data.dropna()
0 1.0
2 3.5
4 7.0
dtype: float64
dropna()는 아래의 방법과 같습니다.
data[data.notnull()]
0 1.0
2 3.5
4 7.0
dtype: float64
지금까지는 Series로 했지만, DataFrame을 기준으로 알아보겠습니다.
rows 혹은 columns를 기준으로 데이터를 없애고 싶을 때 어떻게 해야 하는지 알아보겠습니다.
아래의 예제를 보면 알 수 있지만, dropna()의 default는 any row containig a missing value입니다.
data = pd.DataFrame([[1., 6.5, 3.], [1., NA, NA],
[NA, NA, NA], [NA, 6.5, 3.]])
cleaned = data.dropna()
data
0 1 2
0 1.0 6.5 3.0
1 1.0 NaN NaN
2 NaN NaN NaN
3 NaN 6.5 3.0
cleaned
0 1 2
0 1.0 6.5 3.0
만약 any row가 아니라 all row로 바꾸고 싶다면, how = 'all'을 사용하면 됩니다.
(결측치가 하나라도 있는 행이 아닌, 모든 데이터가 결측치인 행)
data.dropna(how='all')
0 1 2
0 1.0 6.5 3.0
1 1.0 NaN NaN
3 NaN 6.5 3.0
2번째 행만 사라진 것을 볼 수 있습니다.
data[4] = NA
data
0 1 2 4
0 1.0 6.5 3.0 NaN
1 1.0 NaN NaN NaN
2 NaN NaN NaN NaN
3 NaN 6.5 3.0 NaN
data의 4번 column을 추가하고, 모두 NaN으로 넣었습니다.
이때 row가 아닌, column을 기준으로 결측치를 제거하고 싶다면, axis = 1로 설정하면 됩니다.
data.dropna(axis=1, how='all')
0 1 2
0 1.0 6.5 3.0
1 1.0 NaN NaN
2 NaN NaN NaN
3 NaN 6.5 3.0
column을 기준으로, 모든 데이터가 결측치인 열을 삭제했습니다.
새로운 DataFrame으로 다시 실험해보겠습니다.
df = pd.DataFrame(np.random.randn(7, 3))
df.iloc[:4, 1] = NA
df.iloc[:2, 2] = NA
df
0 1 2
0 0.476985 NaN NaN
1 -0.577087 NaN NaN
2 0.523772 NaN 1.343810
3 -0.713544 NaN -2.370232
4 -1.860761 -0.860757 0.560145
5 -1.265934 0.119827 -1.063512
6 0.332883 -2.359419 -0.199543
df.dropna()
0 1 2
4 -1.860761 -0.860757 0.560145
5 -1.265934 0.119827 -1.063512
6 0.332883 -2.359419 -0.199543
결측치가 하나라도 있는 행이 모두 삭제 되었습니다.
만약에 난 결측치가 2개인 행만 삭제하고 싶다! 라면 thresh 파라미터를 넘기면 됩니다.
df.dropna(thresh=2)
0 1 2
2 0.523772 NaN 1.343810
3 -0.713544 NaN -2.370232
4 -1.860761 -0.860757 0.560145
5 -1.265934 0.119827 -1.063512
6 0.332883 -2.359419 -0.199543
3. Filling Missing Data - fillna()
fillna() 함수는 결측치를 채워주는 함수입니다.
위의 df를 재활용했습니다.
fillna(0)은 결측치를 모두 0으로 만듧니다.
df.fillna(0)
0 1 2
0 0.476985 0.000000 0.000000
1 -0.577087 0.000000 0.000000
2 0.523772 0.000000 1.343810
3 -0.713544 0.000000 -2.370232
4 -1.860761 -0.860757 0.560145
5 -1.265934 0.119827 -1.063512
6 0.332883 -2.359419 -0.199543
만약 Column마다 다르게 데이터를 넣고 싶다면 딕셔너리 형태로 파라미터를 넣으면 됩니다.
df.fillna({1: 0.5, 2: 0})
0 1 2
0 0.476985 0.500000 0.000000
1 -0.577087 0.500000 0.000000
2 0.523772 0.500000 1.343810
3 -0.713544 0.500000 -2.370232
4 -1.860761 -0.860757 0.560145
5 -1.265934 0.119827 -1.063512
6 0.332883 -2.359419 -0.199543
만약 즉시 df를 업데이트하고 싶다면, inplace = True를 하면 됩니다.
_ = df.fillna(0, inplace=True)
df
0 1 2
0 0.476985 0.000000 0.000000
1 -0.577087 0.000000 0.000000
2 0.523772 0.000000 1.343810
3 -0.713544 0.000000 -2.370232
4 -1.860761 -0.860757 0.560145
5 -1.265934 0.119827 -1.063512
6 0.332883 -2.359419 -0.199543
다시 새로운 DataFrame으로 테스트하겠습니다.
df = pd.DataFrame(np.random.randn(6, 3))
df.iloc[2:, 1] = NA
df.iloc[4:, 2] = NA
df
0 1 2
0 -1.541996 -0.970736 -1.307030
1 0.286350 0.377984 -0.753887
2 0.331286 NaN 0.069877
3 0.246674 NaN 1.004812
4 1.327195 NaN NaN
5 0.022185 NaN NaN
2행 이후, 1열을 모두 NaN, 4행 이후, 2열을 모두 NaN 처리했습니다.
이때 method = 'ffill'을 사용하면, 위의 데이터와 똑같이 집어넣습니다.
df.fillna(method='ffill')
0 1 2
0 -1.541996 -0.970736 -1.307030
1 0.286350 0.377984 -0.753887
2 0.331286 0.377984 0.069877
3 0.246674 0.377984 1.004812
4 1.327195 0.377984 1.004812
5 0.022185 0.377984 1.004812
이때도 limit = 2를 하면, 최대 2개까지만 보간합니다.
df.fillna(method='ffill', limit=2)
0 1 2
0 -1.541996 -0.970736 -1.307030
1 0.286350 0.377984 -0.753887
2 0.331286 0.377984 0.069877
3 0.246674 0.377984 1.004812
4 1.327195 NaN 1.004812
5 0.022185 NaN 1.004812
이렇게 기존에 있는 값으로 채우는 것이 싫다면, 평균을 이용하여 채워넣는 방법도 있습니다.
data.mean() 값을 넣어주면 됩니다.
data = pd.Series([1., NA, 3.5, NA, 7])
data.fillna(data.mean())
0 1.000000
1 3.833333
2 3.500000
3 3.833333
4 7.000000
dtype: float64
이렇게 되면 데이터의 평균값으로 채워 넣게 됩니다.
4. Conclusion
isnull() - 어떤 데이터가 결측 되었는지 True False로 알려줌
dropna() - 기본 설정은 행의 어떤 데이터라도 결측 되었으면 없앰
how = 'all', axis = 1, thresh = 2 파라미터로 조절 가능
fillna() - 안에 들어가는 숫자로 결측치를 채움
딕셔너리 형태로 넣으면 key에 해당하는 column을 value로 바꿈
method = 'ffill'로 하면 위에 있는 값들로 채워 넣음
'Python Library > Pandas' 카테고리의 다른 글
[Pandas - Python] Transforming Data Using a Function or Mapping - map() (함수나 매핑을 이용한 데이터 변환) (0) | 2022.06.13 |
---|---|
[Pandas - Python] Removing Duplicates - drop_duplicates() (중복 제거) (0) | 2022.06.13 |
[Pandas - Python] Pandas 라이브러리와 그룹화 (0) | 2022.02.08 |
[Pandas - Python] Pandas 라이브러리와 함수 적용 (0) | 2022.02.08 |
[Pandas - Python] Pandas 라이브러리와 데이터 수정(Column과 Row, Cell) (0) | 2022.02.07 |