결측값 및 중복값 처리


1
import pandas as pd
1
df = pd.read_csv('korean-idol.csv')

1. 결측값을 제거하기 – dropna()

  • 결측값이 있는 행을 제거:
    (1) df_name .dropna()
    (2) df_name .dropna(axis=0)
  • 결측값이 있는 열을 제거: df_name .dropna(axis=1)
  • NA가 하나라도 있는 경우 제거: df_name .dropna(axis=0, how = ‘any’)
  • 모두가 NA인 경우 제거: df_name .dropna(axis=0, how = ‘all’)
1
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 15 entries, 0 to 14
Data columns (total 8 columns):
 #   Column   Non-Null Count  Dtype  
---  ------   --------------  -----  
 0   이름       15 non-null     object 
 1   그룹       14 non-null     object 
 2   소속사      15 non-null     object 
 3   성별       15 non-null     object 
 4   생년월일     15 non-null     object 
 5   키        13 non-null     float64
 6   혈액형      15 non-null     object 
 7   브랜드평판지수  15 non-null     int64  
dtypes: float64(1), int64(1), object(6)
memory usage: 1.1+ KB
1
df
이름 그룹 소속사 성별 생년월일 혈액형 브랜드평판지수
0 지민 방탄소년단 빅히트 남자 1995-10-13 173.6 A 10523260
1 지드래곤 빅뱅 YG 남자 1988-08-18 177.0 A 9916947
2 강다니엘 NaN 커넥트 남자 1996-12-10 180.0 A 8273745
3 방탄소년단 빅히트 남자 1995-12-30 178.0 AB 8073501
4 화사 마마무 RBW 여자 1995-07-23 162.1 A 7650928
5 정국 방탄소년단 빅히트 남자 1997-09-01 178.0 A 5208335
6 민현 뉴이스트 플레디스 남자 1995-08-09 182.3 O 4989792
7 소연 아이들 큐브 여자 1998-08-26 NaN B 4668615
8 방탄소년단 빅히트 남자 1992-12-04 179.2 O 4570308
9 하성운 핫샷 스타크루이엔티 남자 1994-03-22 167.1 A 4036489
10 태연 소녀시대 SM 여자 1989-03-09 NaN A 3918661
11 차은우 아스트로 판타지오 남자 1997-03-30 183.0 B 3506027
12 백호 뉴이스트 플레디스 남자 1995-07-21 175.0 AB 3301654
13 JR 뉴이스트 플레디스 남자 1995-06-08 176.0 O 3274137
14 슈가 방탄소년단 빅히트 남자 1993-03-09 174.0 O 2925442

(1) 결측값이 있는 행 제거

1
df.dropna()
이름 그룹 소속사 성별 생년월일 혈액형 브랜드평판지수
0 지민 방탄소년단 빅히트 남자 1995-10-13 173.6 A 10523260
1 지드래곤 빅뱅 YG 남자 1988-08-18 177.0 A 9916947
3 방탄소년단 빅히트 남자 1995-12-30 178.0 AB 8073501
4 화사 마마무 RBW 여자 1995-07-23 162.1 A 7650928
5 정국 방탄소년단 빅히트 남자 1997-09-01 178.0 A 5208335
6 민현 뉴이스트 플레디스 남자 1995-08-09 182.3 O 4989792
8 방탄소년단 빅히트 남자 1992-12-04 179.2 O 4570308
9 하성운 핫샷 스타크루이엔티 남자 1994-03-22 167.1 A 4036489
11 차은우 아스트로 판타지오 남자 1997-03-30 183.0 B 3506027
12 백호 뉴이스트 플레디스 남자 1995-07-21 175.0 AB 3301654
13 JR 뉴이스트 플레디스 남자 1995-06-08 176.0 O 3274137
14 슈가 방탄소년단 빅히트 남자 1993-03-09 174.0 O 2925442
1
df.dropna(axis = 0)
이름 그룹 소속사 성별 생년월일 혈액형 브랜드평판지수
0 지민 방탄소년단 빅히트 남자 1995-10-13 173.6 A 10523260
1 지드래곤 빅뱅 YG 남자 1988-08-18 177.0 A 9916947
3 방탄소년단 빅히트 남자 1995-12-30 178.0 AB 8073501
4 화사 마마무 RBW 여자 1995-07-23 162.1 A 7650928
5 정국 방탄소년단 빅히트 남자 1997-09-01 178.0 A 5208335
6 민현 뉴이스트 플레디스 남자 1995-08-09 182.3 O 4989792
8 방탄소년단 빅히트 남자 1992-12-04 179.2 O 4570308
9 하성운 핫샷 스타크루이엔티 남자 1994-03-22 167.1 A 4036489
11 차은우 아스트로 판타지오 남자 1997-03-30 183.0 B 3506027
12 백호 뉴이스트 플레디스 남자 1995-07-21 175.0 AB 3301654
13 JR 뉴이스트 플레디스 남자 1995-06-08 176.0 O 3274137
14 슈가 방탄소년단 빅히트 남자 1993-03-09 174.0 O 2925442

(2) 결측 값이 있는 열 제거

1
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 15 entries, 0 to 14
Data columns (total 8 columns):
 #   Column   Non-Null Count  Dtype  
---  ------   --------------  -----  
 0   이름       15 non-null     object 
 1   그룹       14 non-null     object 
 2   소속사      15 non-null     object 
 3   성별       15 non-null     object 
 4   생년월일     15 non-null     object 
 5   키        13 non-null     float64
 6   혈액형      15 non-null     object 
 7   브랜드평판지수  15 non-null     int64  
dtypes: float64(1), int64(1), object(6)
memory usage: 1.1+ KB
1
df.dropna(axis=1)
이름 소속사 성별 생년월일 혈액형 브랜드평판지수
0 지민 빅히트 남자 1995-10-13 A 10523260
1 지드래곤 YG 남자 1988-08-18 A 9916947
2 강다니엘 커넥트 남자 1996-12-10 A 8273745
3 빅히트 남자 1995-12-30 AB 8073501
4 화사 RBW 여자 1995-07-23 A 7650928
5 정국 빅히트 남자 1997-09-01 A 5208335
6 민현 플레디스 남자 1995-08-09 O 4989792
7 소연 큐브 여자 1998-08-26 B 4668615
8 빅히트 남자 1992-12-04 O 4570308
9 하성운 스타크루이엔티 남자 1994-03-22 A 4036489
10 태연 SM 여자 1989-03-09 A 3918661
11 차은우 판타지오 남자 1997-03-30 B 3506027
12 백호 플레디스 남자 1995-07-21 AB 3301654
13 JR 플레디스 남자 1995-06-08 O 3274137
14 슈가 빅히트 남자 1993-03-09 O 2925442

(3) NA가 하나라도 있는 경우 행 제거

1
df.dropna(axis=0, how = 'any')
이름 그룹 소속사 성별 생년월일 혈액형 브랜드평판지수
0 지민 방탄소년단 빅히트 남자 1995-10-13 173.6 A 10523260
1 지드래곤 빅뱅 YG 남자 1988-08-18 177.0 A 9916947
3 방탄소년단 빅히트 남자 1995-12-30 178.0 AB 8073501
4 화사 마마무 RBW 여자 1995-07-23 162.1 A 7650928
5 정국 방탄소년단 빅히트 남자 1997-09-01 178.0 A 5208335
6 민현 뉴이스트 플레디스 남자 1995-08-09 182.3 O 4989792
8 방탄소년단 빅히트 남자 1992-12-04 179.2 O 4570308
9 하성운 핫샷 스타크루이엔티 남자 1994-03-22 167.1 A 4036489
11 차은우 아스트로 판타지오 남자 1997-03-30 183.0 B 3506027
12 백호 뉴이스트 플레디스 남자 1995-07-21 175.0 AB 3301654
13 JR 뉴이스트 플레디스 남자 1995-06-08 176.0 O 3274137
14 슈가 방탄소년단 빅히트 남자 1993-03-09 174.0 O 2925442

(4) 모두가 NA인 경우 행 제거

1
import numpy as np
1
df.iloc[10] = np.nan
1
df
이름 그룹 소속사 성별 생년월일 혈액형 브랜드평판지수
0 지민 방탄소년단 빅히트 남자 1995-10-13 173.6 A 10523260.0
1 지드래곤 빅뱅 YG 남자 1988-08-18 177.0 A 9916947.0
2 강다니엘 NaN 커넥트 남자 1996-12-10 180.0 A 8273745.0
3 방탄소년단 빅히트 남자 1995-12-30 178.0 AB 8073501.0
4 화사 마마무 RBW 여자 1995-07-23 162.1 A 7650928.0
5 정국 방탄소년단 빅히트 남자 1997-09-01 178.0 A 5208335.0
6 민현 뉴이스트 플레디스 남자 1995-08-09 182.3 O 4989792.0
7 소연 아이들 큐브 여자 1998-08-26 NaN B 4668615.0
8 방탄소년단 빅히트 남자 1992-12-04 179.2 O 4570308.0
9 하성운 핫샷 스타크루이엔티 남자 1994-03-22 167.1 A 4036489.0
10 NaN NaN NaN NaN NaN NaN NaN NaN
11 차은우 아스트로 판타지오 남자 1997-03-30 183.0 B 3506027.0
12 백호 뉴이스트 플레디스 남자 1995-07-21 175.0 AB 3301654.0
13 JR 뉴이스트 플레디스 남자 1995-06-08 176.0 O 3274137.0
14 슈가 방탄소년단 빅히트 남자 1993-03-09 174.0 O 2925442.0
1
df.dropna(axis=0, how = 'all')
이름 그룹 소속사 성별 생년월일 혈액형 브랜드평판지수
0 지민 방탄소년단 빅히트 남자 1995-10-13 173.6 A 10523260.0
1 지드래곤 빅뱅 YG 남자 1988-08-18 177.0 A 9916947.0
2 강다니엘 NaN 커넥트 남자 1996-12-10 180.0 A 8273745.0
3 방탄소년단 빅히트 남자 1995-12-30 178.0 AB 8073501.0
4 화사 마마무 RBW 여자 1995-07-23 162.1 A 7650928.0
5 정국 방탄소년단 빅히트 남자 1997-09-01 178.0 A 5208335.0
6 민현 뉴이스트 플레디스 남자 1995-08-09 182.3 O 4989792.0
7 소연 아이들 큐브 여자 1998-08-26 NaN B 4668615.0
8 방탄소년단 빅히트 남자 1992-12-04 179.2 O 4570308.0
9 하성운 핫샷 스타크루이엔티 남자 1994-03-22 167.1 A 4036489.0
11 차은우 아스트로 판타지오 남자 1997-03-30 183.0 B 3506027.0
12 백호 뉴이스트 플레디스 남자 1995-07-21 175.0 AB 3301654.0
13 JR 뉴이스트 플레디스 남자 1995-06-08 176.0 O 3274137.0
14 슈가 방탄소년단 빅히트 남자 1993-03-09 174.0 O 2925442.0



2. 결측값을 채워주기 – fillna

df_name [ 'na_col_name ’ ] .fillna(fill_value)

결측값을 채운 데이터프레임을 유지시키려면:
(1) inplace = True 옵션을 추가함
(2) 원 dataframe에 다시 대입함

1
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 15 entries, 0 to 14
Data columns (total 8 columns):
 #   Column   Non-Null Count  Dtype  
---  ------   --------------  -----  
 0   이름       15 non-null     object 
 1   그룹       14 non-null     object 
 2   소속사      15 non-null     object 
 3   성별       15 non-null     object 
 4   생년월일     15 non-null     object 
 5   키        13 non-null     float64
 6   혈액형      15 non-null     object 
 7   브랜드평판지수  15 non-null     int64  
dtypes: float64(1), int64(1), object(6)
memory usage: 1.1+ KB

"키"에 2개의 데이터가 누락, "그룹"에 1개의 데이터가 누락된 것을 확인할 수 있다


2-1. NA값을 특정 숫자로 채우기

  • df_name[ 'na_col_name ’ ] .fillna (new_value, inplace = True)
  • df_name[ 'na_col_name ’ ] = df_name[ 'na_col_name ’ ] .fillna (new_value)

e.g. 누락된 ‘키’ 값을 '-1’로 채워줌

1
df['키'].fillna(-1)
0     173.6
1     177.0
2     180.0
3     178.0
4     162.1
5     178.0
6     182.3
7      -1.0
8     179.2
9     167.1
10     -1.0
11    183.0
12    175.0
13    176.0
14    174.0
Name: 키, dtype: float64

이때는 원 데이터가 변화되지 않음.

1
df['키']
0     173.6
1     177.0
2     180.0
3     178.0
4     162.1
5     178.0
6     182.3
7       NaN
8     179.2
9     167.1
10      NaN
11    183.0
12    175.0
13    176.0
14    174.0
Name: 키, dtype: float64

수정된 데이터를 유지시키려면:

<방법1>

1
df2 = df.copy()
1
df2['키'].fillna(-1, inplace = True)
1
df2['키']
0     173.6
1     177.0
2     180.0
3     178.0
4     162.1
5     178.0
6     182.3
7      -1.0
8     179.2
9     167.1
10     -1.0
11    183.0
12    175.0
13    176.0
14    174.0
Name: 키, dtype: float64

<방법2>

1
df2 = df.copy()
1
df2['키'] = df2['키'].fillna(-1)
1
df2['키']
0     173.6
1     177.0
2     180.0
3     178.0
4     162.1
5     178.0
6     182.3
7      -1.0
8     179.2
9     167.1
10     -1.0
11    183.0
12    175.0
13    176.0
14    174.0
Name: 키, dtype: float64

2-2. NA값을 통계값으로 채우기

  • df_name[ 'na_col_name ’ ] .fillna (df_name[ 'na_col_name ’ ] .mean(), inplace = True)
  • df_name[ 'na_col_name ’ ] = df_name[ 'na_col_name ’ ] .fillna (df_name[ 'na_col_name ’ ] .mean())
1
df2 = df.copy()
1
df2['키']
0     173.6
1     177.0
2     180.0
3     178.0
4     162.1
5     178.0
6     182.3
7       NaN
8     179.2
9     167.1
10      NaN
11    183.0
12    175.0
13    176.0
14    174.0
Name: 키, dtype: float64

(1) 평균으로 대체

1
df2['키'].mean()
175.79230769230767

1
df2['키'].fillna(df2['키'].mean(), inplace = True)
1
df2['키'] = df2['키'].fillna(df2['키'].mean())
1
df2['키']
0     173.600000
1     177.000000
2     180.000000
3     178.000000
4     162.100000
5     178.000000
6     182.300000
7     175.792308
8     179.200000
9     167.100000
10    175.792308
11    183.000000
12    175.000000
13    176.000000
14    174.000000
Name: 키, dtype: float64

(2) 중위값으로 대체

1
df2 = df.copy()
1
df2['키'].median()
177.0

1
df2['키'].fillna(df2['키'].median(), inplace = True)
1
df2['키'] = df2['키'].fillna(df2['키'].median())
1
df2['키']
0     173.6
1     177.0
2     180.0
3     178.0
4     162.1
5     178.0
6     182.3
7     177.0
8     179.2
9     167.1
10    177.0
11    183.0
12    175.0
13    176.0
14    174.0
Name: 키, dtype: float64



3. 중복된 값을 제거하기 – drop_duplicates

1
df = pd.read_csv('korean-idol.csv')
1
df
이름 그룹 소속사 성별 생년월일 혈액형 브랜드평판지수
0 지민 방탄소년단 빅히트 남자 1995-10-13 173.6 A 10523260
1 지드래곤 빅뱅 YG 남자 1988-08-18 177.0 A 9916947
2 강다니엘 NaN 커넥트 남자 1996-12-10 180.0 A 8273745
3 방탄소년단 빅히트 남자 1995-12-30 178.0 AB 8073501
4 화사 마마무 RBW 여자 1995-07-23 162.1 A 7650928
5 정국 방탄소년단 빅히트 남자 1997-09-01 178.0 A 5208335
6 민현 뉴이스트 플레디스 남자 1995-08-09 182.3 O 4989792
7 소연 아이들 큐브 여자 1998-08-26 NaN B 4668615
8 방탄소년단 빅히트 남자 1992-12-04 179.2 O 4570308
9 하성운 핫샷 스타크루이엔티 남자 1994-03-22 167.1 A 4036489
10 태연 소녀시대 SM 여자 1989-03-09 NaN A 3918661
11 차은우 아스트로 판타지오 남자 1997-03-30 183.0 B 3506027
12 백호 뉴이스트 플레디스 남자 1995-07-21 175.0 AB 3301654
13 JR 뉴이스트 플레디스 남자 1995-06-08 176.0 O 3274137
14 슈가 방탄소년단 빅히트 남자 1993-03-09 174.0 O 2925442

3-1. column의 중복값 제거

df_name [“col_name”] .drop_duplicates( keep = … )

  • 여러 개 중복값 (NaN 포함) 중에서 기본적으로 첫번째 것만 유지시키고 나머지는 다 제거한다
  • 하지만 keep 옵션으로 유지하고 싶은 데이터를 선택할 수 있다. [keep: ‘first’ / ‘last’]
  • 이때는 해당 위치의 값만 삭제되고 행 자체는 유지된다

(1) 중복값 중의 첫번째를 유지시킴 (default)

1
df['키']
0     173.6
1     177.0
2     180.0
3       NaN
4     162.1
5     178.0
6     182.3
7       NaN
8     179.2
9     167.1
10      NaN
11    183.0
12    175.0
13    176.0
14    174.0
Name: 키, dtype: float64
1
df['키'].drop_duplicates()  # remove 2nd "178.0" & 2nd "NaN"
0     173.6
1     177.0
2     180.0
3       NaN
4     162.1
5     178.0
6     182.3
8     179.2
9     167.1
11    183.0
12    175.0
13    176.0
14    174.0
Name: 키, dtype: float64
1
df['키'].drop_duplicates(keep='first')
0     173.6
1     177.0
2     180.0
3       NaN
4     162.1
5     178.0
6     182.3
8     179.2
9     167.1
11    183.0
12    175.0
13    176.0
14    174.0
Name: 키, dtype: float64

(2) 중복값 중의 마지막을 유지시킴

1
df['키']
0     173.6
1     177.0
2     180.0
3     178.0
4     162.1
5     178.0
6     182.3
7       NaN
8     179.2
9     167.1
10      NaN
11    183.0
12    175.0
13    176.0
14    174.0
Name: 키, dtype: float64
1
df['키'].drop_duplicates(keep='last')
0     173.6
1     177.0
2     180.0
4     162.1
5     178.0
6     182.3
8     179.2
9     167.1
10      NaN
11    183.0
12    175.0
13    176.0
14    174.0
Name: 키, dtype: float64

이때는 해당위치의 값만 제거되고 행 자체는 유지됨

1
df['키'] = df['키'].drop_duplicates(keep='last')
1
df
이름 그룹 소속사 성별 생년월일 혈액형 브랜드평판지수
0 지민 방탄소년단 빅히트 남자 1995-10-13 173.6 A 10523260
1 지드래곤 빅뱅 YG 남자 1988-08-18 177.0 A 9916947
2 강다니엘 NaN 커넥트 남자 1996-12-10 180.0 A 8273745
3 방탄소년단 빅히트 남자 1995-12-30 NaN AB 8073501
4 화사 마마무 RBW 여자 1995-07-23 162.1 A 7650928
5 정국 방탄소년단 빅히트 남자 1997-09-01 178.0 A 5208335
6 민현 뉴이스트 플레디스 남자 1995-08-09 182.3 O 4989792
7 소연 아이들 큐브 여자 1998-08-26 NaN B 4668615
8 방탄소년단 빅히트 남자 1992-12-04 179.2 O 4570308
9 하성운 핫샷 스타크루이엔티 남자 1994-03-22 167.1 A 4036489
10 태연 소녀시대 SM 여자 1989-03-09 NaN A 3918661
11 차은우 아스트로 판타지오 남자 1997-03-30 183.0 B 3506027
12 백호 뉴이스트 플레디스 남자 1995-07-21 175.0 AB 3301654
13 JR 뉴이스트 플레디스 남자 1995-06-08 176.0 O 3274137
14 슈가 방탄소년단 빅히트 남자 1993-03-09 174.0 O 2925442

3-2. 행 전체 제거

df_name .drop_duplicates(“col_name”, keep = …)

지정한 column에서 중복값이 포함되어 있으면 중복값을 포함한 행을 전체 제거

1
df
이름 그룹 소속사 성별 생년월일 혈액형 브랜드평판지수
0 지민 방탄소년단 빅히트 남자 1995-10-13 173.6 A 10523260
1 지드래곤 빅뱅 YG 남자 1988-08-18 177.0 A 9916947
2 강다니엘 NaN 커넥트 남자 1996-12-10 180.0 A 8273745
3 방탄소년단 빅히트 남자 1995-12-30 NaN AB 8073501
4 화사 마마무 RBW 여자 1995-07-23 162.1 A 7650928
5 정국 방탄소년단 빅히트 남자 1997-09-01 178.0 A 5208335
6 민현 뉴이스트 플레디스 남자 1995-08-09 182.3 O 4989792
7 소연 아이들 큐브 여자 1998-08-26 NaN B 4668615
8 방탄소년단 빅히트 남자 1992-12-04 179.2 O 4570308
9 하성운 핫샷 스타크루이엔티 남자 1994-03-22 167.1 A 4036489
10 태연 소녀시대 SM 여자 1989-03-09 NaN A 3918661
11 차은우 아스트로 판타지오 남자 1997-03-30 183.0 B 3506027
12 백호 뉴이스트 플레디스 남자 1995-07-21 175.0 AB 3301654
13 JR 뉴이스트 플레디스 남자 1995-06-08 176.0 O 3274137
14 슈가 방탄소년단 빅히트 남자 1993-03-09 174.0 O 2925442
1
df['그룹']
0     방탄소년단
1        빅뱅
2       NaN
3     방탄소년단
4       마마무
5     방탄소년단
6      뉴이스트
7       아이들
8     방탄소년단
9        핫샷
10     소녀시대
11     아스트로
12     뉴이스트
13     뉴이스트
14    방탄소년단
Name: 그룹, dtype: object
1
df.drop_duplicates('그룹')
이름 그룹 소속사 성별 생년월일 혈액형 브랜드평판지수
0 지민 방탄소년단 빅히트 남자 1995-10-13 173.6 A 10523260
1 지드래곤 빅뱅 YG 남자 1988-08-18 177.0 A 9916947
2 강다니엘 NaN 커넥트 남자 1996-12-10 180.0 A 8273745
4 화사 마마무 RBW 여자 1995-07-23 162.1 A 7650928
6 민현 뉴이스트 플레디스 남자 1995-08-09 182.3 O 4989792
7 소연 아이들 큐브 여자 1998-08-26 NaN B 4668615
9 하성운 핫샷 스타크루이엔티 남자 1994-03-22 167.1 A 4036489
10 태연 소녀시대 SM 여자 1989-03-09 NaN A 3918661
11 차은우 아스트로 판타지오 남자 1997-03-30 183.0 B 3506027
1
df.drop_duplicates('그룹', keep = 'last')
이름 그룹 소속사 성별 생년월일 혈액형 브랜드평판지수
1 지드래곤 빅뱅 YG 남자 1988-08-18 177.0 A 9916947
2 강다니엘 NaN 커넥트 남자 1996-12-10 180.0 A 8273745
4 화사 마마무 RBW 여자 1995-07-23 162.1 A 7650928
7 소연 아이들 큐브 여자 1998-08-26 NaN B 4668615
9 하성운 핫샷 스타크루이엔티 남자 1994-03-22 167.1 A 4036489
10 태연 소녀시대 SM 여자 1989-03-09 NaN A 3918661
11 차은우 아스트로 판타지오 남자 1997-03-30 183.0 B 3506027
13 JR 뉴이스트 플레디스 남자 1995-06-08 176.0 O 3274137
14 슈가 방탄소년단 빅히트 남자 1993-03-09 174.0 O 2925442