안녕하세요. 모두의 케빈입니다.
오늘은 데이터 프레임의 Null 값을 확인하고 이를 처리하는 방법에 대해 실습해보도록 하겠습니다.
■ 데이터 프레임의 Null 값 확인하기
실습을 위해 데이터 프레임을 불러오겠습니다. 데이터는 Kaggle에서 학생들의 점수(exams.csv) 파일을 사용했습니다.
import pandas as pd
raw_data = pd.read_csv("exams.csv")
df = raw_data.iloc[:,[0,1,5,6,7]].head(100) # 100개의 데이터만 사용
df.columns = ['성별','그룹','수학','국어','영어'] # 데이터 프레임의 컬럼명 재설정
df
호출한 데이터 프레임에 Null 값이 있는지 확인해보겠습니다.
info() : 데이터 프레임의 Null 값 확인하기
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 100 entries, 0 to 99
Data columns (total 5 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 성별 100 non-null object
1 그룹 100 non-null object
2 수학 100 non-null int64
3 국어 100 non-null int64
4 영어 100 non-null int64
dtypes: int64(3), object(2)
memory usage: 4.0+ KB
호출한 데이터 프레임에는 Null 값이 없네요. info() 함수 말고, 다른 방법으로도 Null 값을 확인할 수 있습니다.
isnull()과 isnull().sum()
isnull() 함수는 데이터 프레임의 개별 Cell에 적용되어 각각의 값이 Null 인지, 아닌지를 Boolean 타입으로 반환합니다.
df.isnull()
성별 그룹 수학 국어 영어
0 False False False False False
1 False False False False False
2 False False False False False
3 False False False False False
4 False False False False False
... ... ... ... ... ...
95 False False False False False
96 False False False False False
97 False False False False False
98 False False False False False
99 False False False False False
100 rows × 5 columns
Boolean형에서 True는 1을 False는 0을 의미합니다. isnull() 함수를 통해 Boolean 타입의 데이터 프레임이 반환되면, 이를 세로 방향으로 모두 더해주면 Null 값의 개수를 확인할 수 있습니다. 아래 결과를 보면 Null 값이 하나도 없음을 알 수 있습니다.
df.isnull().sum()
# df.isnull().sum(axis=0) // 위와 동일한 표현. Default가 axis = 0이다.
성별 0
그룹 0
수학 0
국어 0
영어 0
dtype: int64
데이터 프레임에 Null 값 채우기 : None
실습을 위해 데이터 프레임에 Null 값을 채워보겠습니다. 데이터 프레임에서 Null 값은 None을 의미합니다. 아래 결과를 보면 Null 값이 잘 들어간 것으로 보입니다.
import random
# 랜덤으로 데이터 프레임에 Null 값 부여
for i in range(250):
rand_row_num = random.randrange(0,100)
rand_col_num = random.randrange(0,5)
df.iloc[rand_row_num,rand_col_num] = None
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 100 entries, 0 to 99
Data columns (total 5 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 성별 61 non-null object
1 그룹 70 non-null object
2 수학 59 non-null float64
3 국어 61 non-null float64
4 영어 53 non-null float64
dtypes: float64(3), object(2)
memory usage: 4.0+ KB
[Tip #1] 특정 열에서 Null 값이 어디 있는지 알고 싶다면 아래와 같은 방법을 응용해보세요.
# Python의 Fancy Indexing 활용
df[df["그룹"].isnull()].head(10)
성별 그룹 수학 국어 영어
3 male None NaN 78.0 68.0
4 male None 78.0 73.0 NaN
11 female None NaN NaN NaN
13 None None 74.0 74.0 NaN
14 male None 81.0 87.0 NaN
22 None None 71.0 69.0 73.0
25 male None 51.0 NaN NaN
26 female None NaN 60.0 NaN
28 female None 74.0 NaN NaN
31 None None 78.0 74.0 73.0
[Tip #2] Null 값이 아닌 유효 값만 확인하는 방법은 아래와 같습니다.
# Null 값이 아닌 유효값만 데이터 프레임 형태로 반환
df.notnull()
df.notna()
# Null 값이 아닌 유효값의 개수 파악
df.notnull().sum()
df.notna().sum()
dropna() : Null 값이 있는 행과 열을 제거
dropna() 함수는 결측 값이 있는 행 또는 열을 제거합니다. default는 행을 제거(axis=0)합니다.
df.dropna() # default는 axis = 0
df.dropna(axis=0)
#df.dropna(axis=1) # 결측치가 있는 열 전체 제거. 추천하지 않음.
성별 그룹 수학 국어 영어
12 male group D 77.0 87.0 85.0
23 female group B 44.0 55.0 54.0
29 female group A 33.0 54.0 51.0
31 male group A 78.0 74.0 73.0
49 male group C 60.0 63.0 57.0
54 male group D 57.0 57.0 47.0
56 female group C 67.0 80.0 84.0
62 male group E 69.0 67.0 62.0
87 male group D 97.0 93.0 88.0
결측 값을 제거하는 기준을 조절할 수 있습니다. how를 사용하면 되는데요. any는 행 또는 열에 결측 값이 하나라도 있는 경우에 결측 행 또는 열을 제거합니다. dropna()의 default입니다. all은 행 또는 열에 결측 값이 모두 있는 경우에만 행 또는 열을 제거합니다.
df.dropna(how = "any") # default
df.dropna(how = "all")
특정 열에 대해서만 결측 값을 제거하도록 설정할 수 있습니다. subset을 사용하면 지정한 열에 대해서만 결측 값을 제거합니다.
# df.dropna(how = "any", axis = 0, subset =["성별"])
df.dropna(how = "any", axis = 0, subset =["성별", "그룹"]).head(10)
성별 그룹 수학 국어 영어
1 female group D NaN NaN NaN
2 male group E NaN 60.0 50.0
4 male group E NaN 73.0 NaN
5 female group D 63.0 77.0 NaN
11 female group D 80.0 87.0 NaN
12 male group D 77.0 87.0 85.0
14 male group E NaN 87.0 NaN
17 female group C 54.0 62.0 NaN
22 male group B 71.0 NaN 73.0
23 female group B 44.0 55.0 54.0
thresh 옵션은 임계값 이라고도 불립니다. 행 또는 열에 결측 값이 몇 개 이상이어야만 제거하도록 설정할 수 있습니다.
df.dropna(thresh = 2) # 결측 값이 2개 이상 있어야만 제거
성별 그룹 수학 국어 영어
0 male group A NaN 67.0 63.0
1 female group D 40.0 59.0 55.0
2 male group E 59.0 60.0 50.0
3 male group B 77.0 NaN 68.0
4 male None 78.0 73.0 68.0
... ... ... ... ... ...
95 None group C NaN 63.0 67.0
96 female None 95.0 NaN NaN
97 male group B NaN 52.0 NaN
98 male None 63.0 NaN 49.0
99 male None NaN 54.0 53.0
96 rows × 5 columns
fillna() : 결측 값을 지정한 조건으로 채우기
지금까지 결측 값을 제거하는 방법에 대해 알아봤다면 지금부터는 결측 값을 채우는 방법에 대해 알아보도록 하겠습니다. fillna() 함수를 사용하면 사용자가 지정한 옵션에 맞게 결측 값을 다른 값으로 대체합니다.
df.fillna(0).head(5) # 결측 값을 모두 0으로 대체
성별 그룹 수학 국어 영어
0 male group A 0.0 67.0 63.0
1 female group D 40.0 59.0 55.0
2 male group E 59.0 60.0 50.0
3 male group B 77.0 0.0 68.0
4 male 0 78.0 73.0 68.0
5 female 0 0.0 77.0 0.0
6 female group A 0.0 59.0 63.0
7 male 0 0.0 0.0 84.0
그런데 위의 결과를 보면 조금 이상합니다. 그룹 열은 값이 group A, B, C, D, E 등인데 결측 값을 0으로 채우게 되면 데이터를 훼손시키게 됩니다. 따라서 결측 값을 채울 때, 데이터의 특성을 고려해서 따로 채워줘야 할 필요성이 있습니다. 이럴 땐 어떻게 하면 될까요?
열 별로 결측 값을 다르게 채우고 싶은 경우, 아래와 같이 특정 열과 대체 값을 직접 맵핑해주면 됩니다. 수학 열은 수학 열의 평균으로, 국어 열은 국어 열의 중위 값으로, 영어 열은 0으로, 성별 열은 male, 그룹 열은 group A 값으로 결측 값을 대체해보겠습니다.
df.fillna({"수학":df["수학"].mean(), "국어":df["국어"].median(), "영어":0}, inplace = True)
df.fillna({"성별":"male","그룹":"group A"}, inplace = True)
# df.loc[:,"성별"].fillna("group A", inplace= True) 유사한 결과, 다른 접근법
성별 그룹 수학 국어 영어
0 female group A 67.0 67.0 63.0
1 male group D 65.5 67.0 31.0
2 male group A 65.5 67.0 50.0
3 male group B 77.0 78.0 31.0
4 male group A 78.0 73.0 68.0
... ... ... ... ... ...
95 female group C 65.5 63.0 67.0
96 male group E 95.0 100.0 31.0
97 male group A 65.5 52.0 49.0
98 male group A 63.0 50.0 49.0
99 male group A 60.0 67.0 53.0
100 rows × 5 columns
그 외 바로 이전 값이나 뒤의 값으로 대체하는 방법이 있습니다.
df.fillna(method = 'bfill') # 뒤의 값으로 대체
df.fillna(method = 'ffill') # 앞의 값으로 대체
긴 글 읽어주셔서 감사합니다. 궁금한 점은 댓글 남겨주세요. :)
'Python > Pandas' 카테고리의 다른 글
[Python 기초] 데이터 프레임 중복값 제거: drop_duplicate 예제와 사용법 (0) | 2022.11.21 |
---|---|
데이터 프레임 수정의 모든 것: 행, 열, Cell 값 추가/변경/제거 (0) | 2022.11.14 |
[1편] 데이터 프레임 살펴보기: head, tail, columns, values, shape, info, dtypes, describe, value_counts, unique (0) | 2022.11.10 |
DataFrame 병합하기: concat, merge, join (0) | 2022.11.09 |
Data Frame의 행, 열 선택하기: iloc과 loc의 차이점 (0) | 2022.11.07 |
댓글