Python 에서 nan 값을 다루는 법을 알아봅니다.
NaN 이란?
NaN
값은 ‘Not a Number’ 을 뜻합니다. 숫자가 아니라는 뜻이죠. 0을 0으로 나누거나 음수의 제곱근을 구하고자 하면 정상적인 값을 얻지 못할 것입니다. 그럼에도 반환값을 받아야 하는 경우 nan
값을 받게 됩니다. Python에서는 0/0
을 수항하면 Error를 출력하는데, 다른 언어나 python의 numpy 라이브러리를 사용하는 경우 nan
값이 반환되는 것을 볼 수 있습니다.
# nan returned
a = np.array([1,2,3,0,5])
b = np.array([1,2,3,0,0])
print(a/b) # [ 1. 1. 1. nan inf]
nan
은 IEEE 754 라 하여 부동소수점 연산에 관한 표준에서 소개되었습니다. nan
값은 부동소수점 연산 결과에서 특수한 경우를 나타내기 때문에, nan
값은 float
값의 일종입니다. IEEE 754에 의하면 0.01
, 0.00034
, 3.141592
같은 수들과 같은 비트 표현 방식을 사용하지만, 가능한 패턴 중 특수한 경우들을 nan
이라고 부르는 것입니다. 따라서 nan
도 float type의 일종입니다.
nan
값은 연산의 결과가 숫자로 표현될 수 없을 때 사용하기도 하지만, 단순히 값이 부재하는 경우에도 사용합니다.
NaN 특징
Type
nan
은 float
type 입니다.
print(type(float('NaN'))) # <class 'float'>
print(type(np.nan)) # <class 'float'>
print(type(math.nan)) # <class 'float'>
다른 수와의 연산 결과
nan
은 숫자가 아니기 떄문에 다른 숫자들과 연산이 수행되면 결과로 nan
을 받게 됩니다.
x = float('nan')
print( x + 1 ) # nan
print( x * 1 ) # nan
print( x % 1 ) # nan
print( x ** 1 ) # nan
비교 연산 결과
nan
은 다른 수와 순서를 가지지 않습니다. (Unordered) 그렇기 때문에 다른 수와 비교를 비교할 수 없음으로 nan
이 아닌 다른 수와 비교연산을 하였을 때 !=
를 제외하고 모두 False
를 반환하게 됩니다.
x = float('nan')
print( x > 1 ) # False
print( x < 1 ) # False
print( x == 1 ) # False
print( x != 1 ) # True
nan
과 nan
을 비교하였을 때도 결과는 마찬가지입니다.
x = float('nan')
y = float('nan')
print( x > y ) # False
print( x < y ) # False
print( x == y ) # False
print( x != y ) # True
nan
은 nan
과 같지 않습니다. 그렇기 때문에 위 코드에서 같은 x 끼리 비교를 하더라도 결과는 동일합니다.
x = float('nan')
print( x == x ) # False
print( x != x ) # True
값이 NaN인지 확인하기
값이 NaN 인지 확인하는 방법은 다양하고, 사용하는 라이브러리마다 다를 수 있습니다. 아래는 nan
확인을 위한 몇가지 방법입니다.
- python math module :
math.isnan(x)
x = float('nan')
print( math.isnan(x) ) # nan
- numpy :
np.isnan(x)
a = np.array([1,np.nan,3,np.nan,5])
print( np.isnan(a) ) # [False True False True False]
- pandas :
isna()
a = np.array([1,np.nan,3,np.nan,5])
b = np.array([1,2,3,np.nan,np.nan])
df = pd.DataFrame({'a':a,'b':b})
print( df.isna() )
# a b
# 0 False False
# 1 True False
# 2 False False
# 3 True True
# 4 False True
nan
은 nan
과 비교하였을 떄에도 다르다고 판별되는 성질을 이용하여 isna
함수를 만들어 사용할 수 있습니다,
def isna(x):
return x != x
NaN 값 다른 값으로 채우기
numpy나 pandas를 이용하여 데이터를 조작할 때 nan 값을 다른 값으로 대체하는 작업은 꽤 존재합니다.
Numpy
numpy 에서 nan
값을 다른 값으로 대체하는 방법입니다. nan
값을 999
로 바꾼다고 가정합니다.
isnan()
과 boolean index 사용
a = np.array([1,np.nan,3,np.nan,5])
a[np.isnan(a)] = 999
print(a) # [ 1. 999. 3. 999. 5.]
nan_to_num()
사용이 함수는 nan, inf, -inf 모두를 숫자값으로 바꿔버립니다. nan parameter 값의 기본값은 0입니다.
a = np.array([1,np.nan,3,np.nan,5])
print( np.nan_to_num(a,nan=999) ) # [ 1. 999. 3. 999. 5.]
Pandas
pandas 에서 nan
값을 다른 값으로 대체하는 방법입니다. nan
값을 999
로 바꾼다고 가정합니다.
fillna()
사용
a = np.array([1,np.nan,3,np.nan,5])
b = np.array([1,2,3,np.nan,np.nan])
df = pd.DataFrame({'a':a,'b':b})
print( df.fillna(999) )
# a b
# 0 1.0 1.0
# 1 999.0 2.0
# 2 3.0 3.0
# 3 999.0 999.0
# 4 5.0 999.0
replace()
사용
a = np.array([1,np.nan,3,np.nan,5])
b = np.array([1,2,3,np.nan,np.nan])
df = pd.DataFrame({'a':a,'b':b})
print( df.replace(np.nan,999) )
# a b
# 0 1.0 1.0
# 1 999.0 2.0
# 2 3.0 3.0
# 3 999.0 999.0
# 4 5.0 999.0
'Study > Python' 카테고리의 다른 글
Cython으로 속도 향상 꾀하기 (0) | 2022.06.30 |
---|---|
Python unittest module 사용 (0) | 2021.12.23 |
Python os.fork, os.wait 멀티프로세싱 3 (0) | 2021.11.19 |
컴퓨터와 가위바위보 하기 1 (0) | 2021.08.12 |
python argparse를 사용하여 커맨드 라인 인자 처리하기 (0) | 2021.08.04 |
댓글