공공데이터를 활용한 Pandas 기초 실습(결측값 처리~)

작성자 : 양한나

1. 실습에 사용할 데이터를 편집해보자.

  • 오늘 사용할 자료는 학생건강검사_2021년_원자료.csv 파일입니다. 간단한 실습에 알맞게 이것저것 편집해봅시다. 실습자료
import pandas as pd
import numpy as np
df=pd.read_csv("/Users/asd00/Desktop/Ch 03. 데이터 전처리/수정할데이터.csv",encoding='cp949')
df[:5]

#cp949는 한글 인코딩의 한 종류입니다. pd.read_csv()를 사용할 때 종종 오류가 나는 경우가 있으니 오류로 
#'UnicodeDecodeError'가 뜨면 'utf-8'이나 'cp949','euc-kr'등을 사용해보시길 바랍니다.

	학년도	최종가중치	strata		도시규모			시도	성별	생년월일		건강검진일	키		몸무게		건강검진_종합소견
0	2021	34.687664	129		1. 대도시/중소도시	충북	남		20140209	20210610.0	121.0	24.200001	정상
1	2021	41.323936	104		1. 대도시/중소도시	대전	남		20141113	20210719.0	126.0	28.400000	정상
2	2021	24.419891	123		1. 대도시/중소도시	제주	남		20141215	20210409.0	123.8	28.000000	정상(경계)
3	2021	22.338629	109		1. 대도시/중소도시	세종	남		20141011	20210607.0	116.1	21.299999	정상
4	2021	43.717056	120		1. 대도시/중소도시	전북	남		20140204	20210603.0	121.4	23.799999	정밀검사요함

#실습하며 변하는 값들을 용이하게 알아보기 위해 50행까지 잘라줍니다. 
#sample(frac=1)함수를 사용하여 행을 마구잡이로 섞어준 뒤 인덱스를 재정렬하고 df에 저장합니다.
df=df.sample(frac=1).reset_index(drop=True)
df=df.iloc[:50]
print(len(df))
50
#데이터가 잘 섞인 것을 확인할 수 있습니다.
df[:5]
	학년도	최종가중치	strata	도시규모				시도	성별	생년월일		건강검진일	키			몸무게		건강검진_종합소견
0	2021	23.328217	53		1. 대도시/중소도시	경북	여	20060123	20210819.0	160.20000	61.700001	NaN
1	2021	46.369274	112		1. 대도시/중소도시	울산	남	20120816	20210420.0	128.00000	32.200001	NaN
2	2021	124.663180	129		1. 대도시/중소도시	충북	여	20111222	20210715.0	132.89999	27.600000	정상
3	2021	25.170055	85		1. 대도시/중소도시	충북	남	20080218	20210422.0	175.80000	60.000000	정상
4	2021	29.561989	3		2. 읍지역			강원	여	20040318	20210719.0	163.20000	48.599998	NaN
#실습 목적의 데이터 수정이기 때문에 '키'column의 값을 5개 정도를 NaN값으로 바꾸어 주겠습니다.
#무작위로 선택하기 위해 random을 import합니다.
import random
lst=[random.randint(0,50) for _ in range(5)]
for i in lst:
    df[''][i]=np.NaN
#수정한 df는 아래처럼 따로 저장해줍시다.
df.to_csv("/Users/asd00/Desktop/Ch 03. 데이터 전처리/수정된데이터.csv")

2.수정된 데이터를 확인해보자.

#수정된 csv파일을 새로 불러와줍시다.
df=pd.read_csv("/Users/asd00/Desktop/Ch 03. 데이터 전처리/수정된데이터.csv",encoding="utf-8")
#다섯 줄만 확인해볼까요?
df.head()
	Unnamed: 0	학년도	최종가중치	strata		도시규모			시도	성별	생년월일		건강검진일	키			몸무게		건강검진_종합소견
0	0			2021	23.328217	53		1. 대도시/중소도시	경북	여		20060123	20210819.0	160.20000	61.700001	NaN
1	1			2021	46.369274	112		1. 대도시/중소도시	울산	남		20120816	20210420.0	128.00000	32.200001	NaN
2	2			2021	124.663180	129		1. 대도시/중소도시	충북	여		20111222	20210715.0	132.89999	27.600000	정상
3	3			2021	25.170055	85		1. 대도시/중소도시	충북	남		20080218	20210422.0	175.80000	60.000000	정상
4	4			2021	29.561989	3		2. 읍지역		    강원	여		20040318	20210719.0	163.20000	48.599998	NaN
#['Unnamed: 0'] column은 불필요합니다. 
#해당 column을 삭제할 수도 있겠지만 파일을 다른 방식으로 한번 더 불러봅시다.
df=pd.read_csv("/Users/asd00/Desktop/Ch 03. 데이터 전처리/수정된데이터.csv",encoding="utf-8",index_col=0)
df.head()
	학년도	최종가중치	strata	도시규모			시도	성별	생년월일		건강검진일	키			몸무게		건강검진_종합소견
0	2021	23.328217	53	1. 대도시/중소도시	경북	여		20060123	20210819.0	160.20000	61.700001	NaN
1	2021	46.369274	112	1. 대도시/중소도시	울산	남		20120816	20210420.0	128.00000	32.200001	NaN
2	2021	124.663180	129	1. 대도시/중소도시	충북	여		20111222	20210715.0	132.89999	27.600000	정상
3	2021	25.170055	85	1. 대도시/중소도시	충북	남		20080218	20210422.0	175.80000	60.000000	정상
4	2021	29.561989	3		2. 읍지역		강원	여		20040318	20210719.0	163.20000	48.599998	NaN
#실습 이전에 데이터를 쭉 확인해봅시다.
df
#해당 파일은 ['건강검진_종합소견']칼럼에 다량의 결측값을 포함합니다. ['키']칼럼에도 5개의 결측값을 포함하고 있습니다.
#실습에선 이 데이터에 행 또는 열을 추가/삭제하고, 결측값을 여러 방식으로 처리해볼 예정입니다.
	학년도	최종가중치	strata	도시규모			시도	성별	생년월일	건강검진일			키		몸무게		건강검진_종합소견
0	2021	23.328217	53	1. 대도시/중소도시	경북	여	20060123	20210819.0	160.20000	61.700001	NaN
1	2021	46.369274	112	1. 대도시/중소도시	울산	남	20120816	20210420.0	128.00000	32.200001	NaN
2	2021	124.663180	129	1. 대도시/중소도시	충북	여	20111222	20210715.0	132.89999	27.600000	정상
3	2021	25.170055	85	1. 대도시/중소도시	충북	남	20080218	20210422.0	175.80000	60.000000	정상
4	2021	29.561989	3	2. 읍지역			강원	여	20040318	20210719.0	163.20000	48.599998	NaN
5	2021	8.559022	26	2. 읍지역			울산	여	20050519	20210322.0	157.00000	45.000000	정상
6	2021	31.989246	53	1. 대도시/중소도시	경북	여	20080217	20210712.0	158.70000	54.700001	정밀검사요함
7	2021	57.781227	50	1. 대도시/중소도시	경남	남	20071122	20210416.0	163.30000	52.200001	NaN
8	2021	27.776781	14	1. 대도시/중소도시	대구	여	20050905	20210402.0	164.30000	52.400002	정상(경계)
9	2021	30.774267	10	1. 대도시/중소도시	경북	여	20040716	20210616.0	164.70000	52.700001	NaN
10	2021	114.727410	64	1. 대도시/중소도시	서울	여	20071123	20210511.0	154.60001	48.900002	NaN
11	2021	28.404102	10	1. 대도시/중소도시	경북	여	20051216	20210527.0	159.50000	80.199997	정밀검사요함
12	2021	73.986015	120	1. 대도시/중소도시	전북	남	20100112	20210722.0	NaN			46.400002	NaN
13	2021	31.590971	60	1. 대도시/중소도시	대전	여	20060919	20210910.0	NaN			59.200001	NaN
14	2021	22.767038	53	1. 대도시/중소도시	경북	여	20071203	20210427.0	161.50000	70.400002	NaN
15	2021	40.564987	71	1. 대도시/중소도시	인천	남	20080215	20210511.0	161.89999	45.700001	정밀검사요함
16	2021	35.157436	101	1. 대도시/중소도시	대구	여	20140303	20210329.0	124.70000	24.200001	정상
17	2021	22.281324	12	2. 읍지역			경북	여	20050105	20210616.0	155.20000	57.299999	NaN
18	2021	80.866142	20	1. 대도시/중소도시	서울	여	20051025	20210506.0	158.39999	46.900002	NaN
19	2021	17.877020	68	1. 대도시/중소도시	울산	남	20080812	20210414.0	169.50000	74.099998	정밀검사요함
20	2021	28.806343	1	1. 대도시/중소도시	강원	남	20030404	20210506.0	174.10001	69.300003	NaN
21	2021	72.317360	4	1. 대도시/중소도시	경기	여	20030917	20210616.0	160.20000	55.000000	NaN
22	2021	47.379448	119	2. 읍지역			전남	남	20090129	20210511.0	161.50000	71.400002	NaN
23	2021	61.222218	115	1. 대도시/중소도시	인천	남	20110621	20210624.0	137.70000	30.000000	정상
24	2021	24.712151	39	3. 도서벽지/면지역	충남	남	20030301	20210401.0	179.00000	77.000000	NaN
25	2021	35.645729	112	1. 대도시/중소도시	울산	여	20100116	20210405.0	152.50000	58.000000	NaN
26	2021	29.677813	112	1. 대도시/중소도시	울산	여	20130906	20210522.0	129.70000	30.299999	NaN
27	2021	44.383324	88	1. 대도시/중소도시	강원	여	20130820	20210909.0	134.89999	27.100000	NaN
28	2021	20.161478	38	1. 대도시/중소도시	충남	여	20050623	20210702.0	160.89999	56.200001	정상
29	2021	15.181579	65	1. 대도시/중소도시	세종	남	20070929	20210831.0	158.70000	41.400002	NaN
30	2021	95.082298	64	1. 대도시/중소도시	서울	여	20071028	20210510.0	158.70000	57.500000	NaN
31	2021	30.238064	27	1. 대도시/중소도시	인천	여	20031020	20210510.0	164.80000	54.599998	NaN
32	2021	24.965509	60	1. 대도시/중소도시	대전	여	20060106	20210315.0	161.00000	46.000000	NaN
33	2021	43.435921	104	1. 대도시/중소도시	대전	남	20111209	20210702.0	143.70000	39.599998	정밀검사요함
34	2021	79.330093	4	1. 대도시/중소도시	경기	남	20051130	20210518.0	171.20000	51.200001	정밀검사요함
35	2021	56.952087	126	1. 대도시/중소도시	충남	여	20140715	20210408.0	120.60000	26.700001	정밀검사요함
36	2021	8.956521	67	2. 읍지역			세종	여	20070527	20210712.0	NaN			59.200001	NaN
37	2021	542.851750	127	3. 도서벽지/면지역	충남	남	20120220	20210414.0	145.60001	49.799999	NaN
38	2021	21.612099	38	1. 대도시/중소도시	충남	여	20051213	20210520.0	157.80000	49.900002	정밀검사요함
39	2021	48.070133	56	1. 대도시/중소도시	광주	남	20080516	20210626.0	168.70000	46.900002	정밀검사요함
40	2021	60.742973	20	1. 대도시/중소도시	서울	여	20041123	20210701.0	168.60001	65.500000	NaN
41	2021	27.684238	17	1. 대도시/중소도시	대전	여	20040628	20210729.0	161.60001	51.400002	NaN
42	2021	35.701881	56	1. 대도시/중소도시	광주	여	20081230	20210601.0	NaN			63.099998	정밀검사요함
43	2021	15.477712	65	1. 대도시/중소도시	세종	여	20070724	20210510.0	157.10001	54.400002	NaN
44	2021	54.350529	4	1. 대도시/중소도시	경기	여	20050517	20210823.0	162.50000	48.099998	정상
45	2021	46.585281	101	1. 대도시/중소도시	대구	여	20121106	20210621.0	136.30000	29.600000	NaN
46	2021	70.016350	105	1. 대도시/중소도시	부산	남	20100201	20210605.0	143.39999	32.599998	NaN
47	2021	27.585751	82	1. 대도시/중소도시	충남	여	20080301	20210913.0	161.00000	49.200001	정상
48	2021	29.002300	24	1. 대도시/중소도시	울산	여	20040304	20210727.0	171.60001	76.099998	NaN
49	2021	33.326992	10	1. 대도시/중소도시	경북	남	20030614	20210618.0	NaN			56.500000	NaN

3.결측값 확인하기

  • 실습데이터는 50개의 행만 포함하지만, 행이 아주 많은 데이터라면 어디에 결측값이 하나씩 확인할 수 없겠죠?isnull()을 사용하여 df 각 칼럼의 결측값을 확인해봅시다.
df.isnull().sum()
#isnull()은 결측값만 True로 반환합니다. .sum()을 isnull()과 같이 사용하면 각 column의 True 값을 1로 하여 더해줍니다.
학년도           0
최종가중치         0
strata        0
도시규모          0
시도            0
성별            0
생년월일          0
건강검진일         0
키             5
몸무게           0
건강검진_종합소견    31
dtype: int64
#결측치가 포함된 행을 지우고 싶습니다. dropna()는 결측값을 포함한 행을 삭제합니다.
#어떤 문제가 생기는지 확인합시다.
df.dropna()
  • 행이 18개밖에 안 남았습니다. 이유는 ‘건강검진_종합소견’column이 너무 많은 결측값을 포함하기 때문입니다. #때문에 ‘건강검진_종합소견’칼럼을 먼저 지워주도록 하겠습니다.
학년도		최종가중치	strata	도시규모				시도	성별	생년월일	건강검진일		키			몸무게		건강검진_종합소견
2	2021	124.663180	129		1. 대도시/중소도시	충북	여	20111222		20210715.0	132.89999	27.600000	정상
3	2021	25.170055	85		1. 대도시/중소도시	충북	남	20080218		20210422.0	175.80000	60.000000	정상
5	2021	8.559022	26		2. 읍지역			울산	여	20050519		20210322.0	157.00000	45.000000	정상
6	2021	31.989246	53		1. 대도시/중소도시	경북	여	20080217		20210712.0	158.70000	54.700001	정밀검사요함
8	2021	27.776781	14		1. 대도시/중소도시	대구	여	20050905		20210402.0	164.30000	52.400002	정상(경계)
11	2021	28.404102	10		1. 대도시/중소도시	경북	여	20051216		20210527.0	159.50000	80.199997	정밀검사요함
15	2021	40.564987	71		1. 대도시/중소도시	인천	남	20080215		20210511.0	161.89999	45.700001	정밀검사요함
16	2021	35.157436	101		1. 대도시/중소도시	대구	여	20140303		20210329.0	124.70000	24.200001	정상
19	2021	17.877020	68		1. 대도시/중소도시	울산	남	20080812		20210414.0	169.50000	74.099998	정밀검사요함
23	2021	61.222218	115		1. 대도시/중소도시	인천	남	20110621		20210624.0	137.70000	30.000000	정상
28	2021	20.161478	38		1. 대도시/중소도시	충남	여	20050623		20210702.0	160.89999	56.200001	정상
33	2021	43.435921	104		1. 대도시/중소도시	대전	남	20111209		20210702.0	143.70000	39.599998	정밀검사요함
34	2021	79.330093	4		1. 대도시/중소도시	경기	남	20051130		20210518.0	171.20000	51.200001	정밀검사요함
35	2021	56.952087	126		1. 대도시/중소도시	충남	여	20140715		20210408.0	120.60000	26.700001	정밀검사요함
38	2021	21.612099	38		1. 대도시/중소도시	충남	여	20051213		20210520.0	157.80000	49.900002	정밀검사요함
39	2021	48.070133	56		1. 대도시/중소도시	광주	남	20080516		20210626.0	168.70000	46.900002	정밀검사요함
44	2021	54.350529	4		1. 대도시/중소도시	경기	여	20050517		20210823.0	162.50000	48.099998	정상
47	2021	27.585751	82		1. 대도시/중소도시	충남	여	20080301		20210913.0	161.00000	49.200001	정상
#['건겅검진_종합소견']칼럼을 삭제하기 위해 drop()을 사용합니다. 열을 삭제하기 때문에 axis=True
df.drop('건강검진_종합소견',axis=True)[:5]
#해당 column이 잘 지워지는 걸 확인했으니 inplace=True로 저장하고 데이터를 다시 확인해봅시다.
	학년도	최종가중치	strata		도시규모			시도	성별	생년월일	  건강검진일		 키			몸무게
0	2021	23.328217	53		1. 대도시/중소도시	경북	여		20060123	20210819.0	160.20000	61.700001
1	2021	46.369274	112		1. 대도시/중소도시	울산	남		20120816	20210420.0	128.00000	32.200001
2	2021	124.663180	129		1. 대도시/중소도시	충북	여		20111222	20210715.0	132.89999	27.600000
3	2021	25.170055	85		1. 대도시/중소도시	충북	남		20080218	20210422.0	175.80000	60.000000
4	2021	29.561989	3		2. 읍지역			강원	여		20040318	20210719.0	163.20000	48.599998
#칼럼이 잘 지워진 걸 확인했으면 inplace=True를 사용하여 df를 저장해줍시다.
df.drop('건강검진_종합소견',axis=1,inplace=True)
#결측값의 개수를 다시 확인해볼까요?
df.isnull().sum()
학년도       0
최종가중치     0
strata    0
도시규모      0
시도        0
성별        0
생년월일      0
건강검진일     0
키         5
몸무게       0
dtype: int64
  • 결측값이 포함된 행을 지우지 말고 [‘키’]의 결측값을 대체해봅시다.해당 실습을 위해 결측값을 가진 행 5개와 다른 행 5개를 df2에 저장해줍시다. 별 의미는 없고, 실습결과 확인을 위해 df를 다 출력하면 포스트가 너무 길어질 것 같아서입니다.. 빈 데이터프레임을 만들어줍니다.
df2=pd.DataFrame()
#isna()메소드는 결측값이 있을 때 True를 반환합니다. 
#append()메소드로 데이터를 추가할 수 있습니다.
for i in range(50):
    if pd.isna(df.loc[i]['']):
        involveNan=df.loc[i]
        df2=df2.append(involveNan,ignore_index=True)
df2

	학년도	최종가중치	strata	도시규모				시도	성별	생년월일		건강검진일		키		몸무게
0	2021	73.986015	120		1. 대도시/중소도시	전북	남		20100112	20210722.0		NaN		46.400002
1	2021	31.590971	60		1. 대도시/중소도시	대전	여		20060919	20210910.0		NaN		59.200001
2	2021	8.956521	67		2. 읍지역			세종	여		20070527	20210712.0		NaN		59.200001
3	2021	35.701881	56		1. 대도시/중소도시	광주	여		20081230	20210601.0		NaN		63.099998
4	2021	33.326992	10		1. 대도시/중소도시	경북	남		20030614	20210618.0		NaN		56.500000
#결측값을 포함하지 않은 행 5개도 포함하겠습니다.
a=True
while a==True:
    random_numbers = random.sample(range(0,50), 5)
    for i in random_numbers:
        if pd.isna(df.loc[i]['']):
            pass
        else:
            a=False
for i in random_numbers:
    df2=df2.append(df.loc[i],ignore_index=True)
df2
	학년도	최종가중치	strata		도시규모			시도	성별	생년월일		건강검진일	키			몸무게
0	2021	73.986015	120		1. 대도시/중소도시	전북	남		20100112	20210722.0	NaN			46.400002
1	2021	31.590971	60		1. 대도시/중소도시	대전	여		20060919	20210910.0	NaN			59.200001
2	2021	8.956521	67		2. 읍지역			세종	여		20070527	20210712.0	NaN			59.200001
3	2021	35.701881	56		1. 대도시/중소도시	광주	여		20081230	20210601.0	NaN			63.099998
4	2021	33.326992	10		1. 대도시/중소도시	경북	남		20030614	20210618.0	NaN			56.500000
5	2021	21.612099	38		1. 대도시/중소도시	충남	여		20051213	20210520.0	157.80000	49.900002
6	2021	124.663180	129		1. 대도시/중소도시	충북	여		20111222	20210715.0	132.89999	27.600000
7	2021	70.016350	105		1. 대도시/중소도시	부산	남		20100201	20210605.0	143.39999	32.599998
8	2021	72.317360	4		1. 대도시/중소도시	경기	여		20030917	20210616.0	160.20000	55.000000
9	2021	54.350529	4		1. 대도시/중소도시	경기	여		20050517	20210823.0	162.50000	48.099998
df2=df2.sample(frac=1).reset_index(drop=True)
df2
	학년도	최종가중치	strata	   도시규모			시도	성별	생년월일		건강검진일	키			몸무게
0	2021	33.326992	10		1. 대도시/중소도시	경북	남		20030614	20210618.0	NaN			56.500000
1	2021	70.016350	105		1. 대도시/중소도시	부산	남		20100201	20210605.0	143.39999	32.599998
2	2021	8.956521	67		2. 읍지역			세종	여		20070527	20210712.0	NaN			59.200001
3	2021	124.663180	129		1. 대도시/중소도시	충북	여		20111222	20210715.0	132.89999	27.600000
4	2021	21.612099	38		1. 대도시/중소도시	충남	여		20051213	20210520.0	157.80000	49.900002
5	2021	73.986015	120		1. 대도시/중소도시	전북	남		20100112	20210722.0	NaN			46.400002
6	2021	35.701881	56		1. 대도시/중소도시	광주	여		20081230	20210601.0	NaN			63.099998
7	2021	72.317360	4		1. 대도시/중소도시	경기	여		20030917	20210616.0	160.20000	55.000000
8	2021	31.590971	60		1. 대도시/중소도시	대전	여		20060919	20210910.0	NaN			59.200001
9	2021	54.350529	4		1. 대도시/중소도시	경기	여		20050517	20210823.0	162.50000	48.099998
  • 결측값을 특정값 ‘0’으로 대체해봅시다.
df2.fillna(0)
	학년도	최종가중치	strata		도시규모			시도	성별	생년월일		건강검진일	키			몸무게
0	2021	33.326992	10		1. 대도시/중소도시	경북	남		20030614	20210618.0	0.00000		56.500000
1	2021	70.016350	105		1. 대도시/중소도시	부산	남		20100201	20210605.0	143.39999	32.599998
2	2021	8.956521	67		2. 읍지역			세종	여		20070527	20210712.0	0.00000		59.200001
3	2021	124.663180	129		1. 대도시/중소도시	충북	여		20111222	20210715.0	132.89999	27.600000
4	2021	21.612099	38		1. 대도시/중소도시	충남	여		20051213	20210520.0	157.80000	49.900002
5	2021	73.986015	120		1. 대도시/중소도시	전북	남		20100112	20210722.0	0.00000		46.400002
6	2021	35.701881	56		1. 대도시/중소도시	광주	여		20081230	20210601.0	0.00000		63.099998
7	2021	72.317360	4		1. 대도시/중소도시	경기	여		20030917	20210616.0	160.20000	55.000000
8	2021	31.590971	60		1. 대도시/중소도시	대전	여		20060919	20210910.0	0.00000		59.200001
9	2021	54.350529	4		1. 대도시/중소도시	경기	여		20050517	20210823.0	162.50000	48.099998
  • 결측 값을 직전 행의 값으로 대체합니다. ‘ffill’은 직전 행의 값으로 대체합니다. 다음 행이 존재하지 않거나 NaN이면 채워주지 않습니다.
df2.fillna(method='ffill')
	학년도	최종가중치	strata		도시규모			시도	성별	생년월일		건강검진일	키			몸무게
0	2021	33.326992	10		1. 대도시/중소도시	경북	남		20030614	20210618.0	NaN			56.500000
1	2021	70.016350	105		1. 대도시/중소도시	부산	남		20100201	20210605.0	143.39999	32.599998
2	2021	8.956521	67		2. 읍지역			세종	여		20070527	20210712.0	143.39999	59.200001
3	2021	124.663180	129		1. 대도시/중소도시	충북	여		20111222	20210715.0	132.89999	27.600000
4	2021	21.612099	38		1. 대도시/중소도시	충남	여		20051213	20210520.0	157.80000	49.900002
5	2021	73.986015	120		1. 대도시/중소도시	전북	남		20100112	20210722.0	157.80000	46.400002
6	2021	35.701881	56		1. 대도시/중소도시	광주	여		20081230	20210601.0	157.80000	63.099998
7	2021	72.317360	4		1. 대도시/중소도시	경기	여		20030917	20210616.0	160.20000	55.000000
8	2021	31.590971	60		1. 대도시/중소도시	대전	여		20060919	20210910.0	160.20000	59.200001
9	2021	54.350529	4		1. 대도시/중소도시	경기	여		20050517	20210823.0	162.50000	48.099998
#평균 값 대체
df2.fillna(df2.mean()[''])
	학년도	최종가중치	strata		도시규모			시도	성별	생년월일		건강검진일		키		몸무게
0	2021	33.326992	10		1. 대도시/중소도시	경북	남		20030614	20210618.0	151.359996	56.500000
1	2021	70.016350	105		1. 대도시/중소도시	부산	남		20100201	20210605.0	143.399990	32.599998
2	2021	8.956521	67		2. 읍지역			세종	여		20070527	20210712.0	151.359996	59.200001
3	2021	124.663180	129		1. 대도시/중소도시	충북	여		20111222	20210715.0	132.899990	27.600000
4	2021	21.612099	38		1. 대도시/중소도시	충남	여		20051213	20210520.0	157.800000	49.900002
5	2021	73.986015	120		1. 대도시/중소도시	전북	남		20100112	20210722.0	151.359996	46.400002
6	2021	35.701881	56		1. 대도시/중소도시	광주	여		20081230	20210601.0	151.359996	63.099998
7	2021	72.317360	4		1. 대도시/중소도시	경기	여		20030917	20210616.0	160.200000	55.000000
8	2021	31.590971	60		1. 대도시/중소도시	대전	여		20060919	20210910.0	151.359996	59.200001
9	2021	54.350529	4		1. 대도시/중소도시	경기	여		20050517	20210823.0	162.500000	48.099998
  • 이번엔 좀 더 의미있는 값으로 대체해봅시다.df2 집단의 키가 다양하기 때문에 결측값을 가진 행의 몸무게로 키를 예상하겠습니다. 평균 bmi를 활용하겠습니다. 평균 bmi를 20이라고 칩시다.
#bmi= (몸무게) ÷ (키*0.01)2
# 키=sqrt(몸무게/20)*100
import math
for i in range(10):
    if pd.isna(df2.loc[i]['']):
        a=df2.loc[i,'몸무게']
        df2.loc[i,'']=math.sqrt(a/20)*100
df2
	학년도	최종가중치	strata		도시규모			시도	성별	생년월일		건강검진일		키			몸무게
0	2021	33.326992	10		1. 대도시/중소도시	경북	남		20030614	20210618.0	168.077363	56.500000
1	2021	70.016350	105		1. 대도시/중소도시	부산	남		20100201	20210605.0	143.399990	32.599998
2	2021	8.956521	67		2. 읍지역			세종	여		20070527	20210712.0	172.046507	59.200001
3	2021	124.663180	129		1. 대도시/중소도시	충북	여		20111222	20210715.0	132.899990	27.600000
4	2021	21.612099	38		1. 대도시/중소도시	충남	여		20051213	20210520.0	157.800000	49.900002
5	2021	73.986015	120		1. 대도시/중소도시	전북	남		20100112	20210722.0	152.315465	46.400002
6	2021	35.701881	56		1. 대도시/중소도시	광주	여		20081230	20210601.0	177.623194	63.099998
7	2021	72.317360	4		1. 대도시/중소도시	경기	여		20030917	20210616.0	160.200000	55.000000
8	2021	31.590971	60		1. 대도시/중소도시	대전	여		20060919	20210910.0	172.046507	59.200001
9	2021	54.350529	4		1. 대도시/중소도시	경기	여		20050517	20210823.0	162.500000	48.099998
  • 같은 방법으로 df의 결측값도 대체합시다. 이제 어떤 칼럼도 결측값을 포함하지 않습니다.
for i in range(50):
    if pd.isna(df.loc[i]['']):
        a=df.loc[i,'몸무게']
        df.loc[i,'']=math.sqrt(a/20)*100
df.isnull().sum()
학년도       0
최종가중치     0
strata    0
도시규모      0
시도        0
성별        0
생년월일      0
건강검진일     0
키         0
몸무게       0
dtype: int64

4.타입변환

  • 각 colunm의 타입을 확인합시다.
df.dtypes
학년도         int64
최종가중치     float64
strata      int64
도시규모       object
시도         object
성별         object
생년월일        int64
건강검진일     float64
키         float64
몸무게       float64
dtype: object
  • ‘키’와 ‘몸무게’를 정수형으로 변환해줍시다.
df.astype({'':'int','몸무게':'int'})[:5]
	학년도	최종가중치	strata	도시규모				시도	성별	생년월일		건강검진일	키	몸무게
0	2021	23.328217	53		1. 대도시/중소도시	경북	여		20060123	20210819.0	160		61
1	2021	46.369274	112		1. 대도시/중소도시	울산	남		20120816	20210420.0	128		32
2	2021	124.663180	129		1. 대도시/중소도시	충북	여		20111222	20210715.0	132		27
3	2021	25.170055	85		1. 대도시/중소도시	충북	남		20080218	20210422.0	175		60
4	2021	29.561989	3		2. 읍지역			강원	여		20040318	20210719.0	163		48
  • astype을 적용한 값과 df의 원래 값을 비교해보면 float형을 int형으로 바꾸면서 소수점을 버린 걸 알 수 있습니다.
df[:5]
	학년도	최종가중치	strata	도시규모				시도	성별	생년월일	  건강검진일		키			몸무게
0	2021	23.328217	53		1. 대도시/중소도시	경북	여		20060123	20210819.0	160.20000	61.700001
1	2021	46.369274	112		1. 대도시/중소도시	울산	남		20120816	20210420.0	128.00000	32.200001
2	2021	124.663180	129		1. 대도시/중소도시	충북	여		20111222	20210715.0	132.89999	27.600000
3	2021	25.170055	85		1. 대도시/중소도시	충북	남		20080218	20210422.0	175.80000	60.000000
4	2021	29.561989	3		2. 읍지역			강원	여		20040318	20210719.0	163.20000	48.599998
  • 그대로 저장해줍시다.
df=df.astype({'':'int','몸무게':'int'})
df.head()
	학년도	최종가중치	strata	도시규모				시도	성별	  생년월일	건강검진일	키	몸무게
0	2021	23.328217	53		1. 대도시/중소도시	경북	여		20060123	20210819.0	160		61
1	2021	46.369274	112		1. 대도시/중소도시	울산	남		20120816	20210420.0	128		32
2	2021	124.663180	129		1. 대도시/중소도시	충북	여		20111222	20210715.0	132		27
3	2021	25.170055	85		1. 대도시/중소도시	충북	남		20080218	20210422.0	175		60
4	2021	29.561989	3		2. 읍지역			강원	여		20040318	20210719.0	163		48
  • 타입을 다시 확인합시다.
df.dtypes
학년도         int64
최종가중치     float64
strata      int64
도시규모       object
시도         object
성별         object
생년월일        int64
건강검진일     float64
키           int32
몸무게         int32
dtype: object
#한 학생의 키를 '-'로 바꾸어보겠습니다. 
df.loc[3,'']='-'
df.astype({'':'int'})
#'키'가 '-'문자를 포함하기 때문에 int형으로 바꿀 수 없습니다.
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[200], line 1
----> 1 df.astype({'':'int'})
      2 #'키'가 '-'문자를 포함하기 때문에 int형으로 바꿀 수 없습니다.

File c:\Users\asd00\AppData\Local\Programs\Python\Python311\Lib\site-packages\pandas\core\generic.py:6226, in NDFrame.astype(self, dtype, copy, errors)
   6224             res_col = col.copy() if copy else col
   6225         else:
-> 6226             res_col = col.astype(dtype=cdt, copy=copy, errors=errors)
   6227         results.append(res_col)
   6229 elif is_extension_array_dtype(dtype) and self.ndim > 1:
   6230     # GH 18099/22869: columnwise conversion to extension dtype
   6231     # GH 24704: use iloc to handle duplicate column names
   6232     # TODO(EA2D): special case not needed with 2D EAs

File c:\Users\asd00\AppData\Local\Programs\Python\Python311\Lib\site-packages\pandas\core\generic.py:6240, in NDFrame.astype(self, dtype, copy, errors)
   6233     results = [
   6234         self.iloc[:, i].astype(dtype, copy=copy)
   6235         for i in range(len(self.columns))
   6236     ]
   6238 else:
   6239     # else, only a single dtype is given
-> 6240     new_data = self._mgr.astype(dtype=dtype, copy=copy, errors=errors)
   6241     return self._constructor(new_data).__finalize__(self, method="astype")
...
    169     # Explicit copy, or required since NumPy can't view from / to object.
--> 170     return arr.astype(dtype, copy=True)
    172 return arr.astype(dtype, copy=copy)

ValueError: invalid literal for int() with base 10: '-'
Output is truncated. View as a scrollable element or open in a text editor. Adjust cell output settings...
  • to_nemeric은 datatype을 숫자형식으로 바꿔줍니다. errors=’coerce’ 변환할 수 없는 값을 결측값으로 지정합니다.ㅍ’-‘가 결측값으로 바뀐 걸 확인할 수 있습니다.
df['']=pd.to_numeric(df[''],errors='coerce')
  • 이제 결측값을 삭제하고 ‘키’칼럼을 int형으로 바꿀 수 있습니다.
df=df.dropna()
df.astype({'':'int'})
df.reset_index(inplace=True)
df.drop(['index'],axis=1,inplace=True)
df[:5]
	학년도	최종가중치	strata	도시규모			시도	성별	생년월일		건강검진일	키	몸무게
0	2021	23.328217	53	1. 대도시/중소도시	경북	여		20060123	20210819.0	160.0	61
1	2021	46.369274	112	1. 대도시/중소도시	울산	남		20120816	20210420.0	128.0	32
2	2021	124.663180	129	1. 대도시/중소도시	충북	여		20111222	20210715.0	132.0	27
3	2021	29.561989	3	2. 읍지역			강원	여		20040318	20210719.0	163.0	48
4	2021	8.559022	26	2. 읍지역			울산	여		20050519	20210322.0	157.0	45
df[:5]
	학년도	최종가중치	strata	도시규모	시도		성별	생년월일		건강검진일	키		몸무게
0	2021	23.328217	53	1. 대도시/중소도시	경북	여	20060123	20210819.0	160.0	61
1	2021	46.369274	112	1. 대도시/중소도시	울산	남	20120816	20210420.0	128.0	32
2	2021	124.663180	129	1. 대도시/중소도시	충북	여	20111222	20210715.0	132.0	27
3	2021	29.561989	3	2. 읍지역			강원	여	20040318	20210719.0	163.0	48
4	2021	8.559022	26	2. 읍지역			울산	여	20050519	20210322.0	157.0	45

5.콜럼 추가 삭제

  • 추가(append)와 삭제(drop)는 위에서 데이터를 수정하며 다루었기 때문에 그냥 넘어갑시다. 다른 칼럼들을 이용하여 [‘bmi’]칼럼을 추가해봅시다.
df['bmi']=df['몸무게']/(df['']*0.01)**2
df[:5]
	학년도	최종가중치	strata		도시규모	시도	성별		생년월일		건강검진일	키		몸무게	bmi
0	2021	23.328217	53		1. 대도시/중소도시	경북	여	20060123	20210819.0	160.0		61	23.828125
1	2021	46.369274	112		1. 대도시/중소도시	울산	남	20120816	20210420.0	128.0		32	19.531250
2	2021	124.663180	129		1. 대도시/중소도시	충북	여	20111222	20210715.0	132.0		27	15.495868
3	2021	29.561989	3		2. 읍지역			강원	여	20040318	20210719.0	163.0		48	18.066167
4	2021	8.559022	26		2. 읍지역			울산	여	20050519	20210322.0	157.0		45	18.256319

6.apply/map을 활용한 데이터 변환

  • ‘bmi’column을 활용하여 ‘bmi’가 18.5~22.9면 ‘정상’, 그 미만면 ‘저체중’ ,나머지는 과체중으로 표시한 ‘비만도’column을 만들어봅시다.
df['비만도']=0
df[:5]
학년도	최종가중치		strata	도시규모				시도	성별	생년월일	건강검진일		키		몸무게	bmi		비만도
0	2021	23.328217	53		1. 대도시/중소도시	경북	여		20060123	20210819.0	160.0	61 		23.828125	0
1	2021	46.369274	112		1. 대도시/중소도시	울산	남		20120816	20210420.0	128.0	32		19.531250	0
2	2021	124.663180	129		1. 대도시/중소도시	충북	여		20111222	20210715.0	132.0	27		15.495868	0
3	2021	29.561989	3		2. 읍지역			강원	여		20040318	20210719.0	163.0	48		18.066167	0
4	2021	8.559022	26		2. 읍지역			울산	여		20050519	20210322.0	157.0	45		18.256319	0
a=df[(df['bmi']>=18.5) &( df['bmi']<=22.9)]
df['비만도'][a.index]='정상'
a=df[df['bmi']<18.5]
df['비만도'][a.index]='저체중'
a=df[df['bmi']>22.9]
df['비만도'][a.index]='과체중'
df[:5]
학년도	최종가중치		strata	도시규모				시도	성별	생년월일		건강검진일	키		몸무게	bmi			비만도
0	2021	23.328217	53		1. 대도시/중소도시	경북	여		20060123	20210819.0	160.0	61		23.828125	과체중
1	2021	46.369274	112		1. 대도시/중소도시	울산	남		20120816	20210420.0	128.0	32		19.531250	정상
2	2021	124.663180	129		1. 대도시/중소도시	충북	여		20111222	20210715.0	132.0	27		15.495868	저체중
3	2021	29.561989	3		2. 읍지역			강원	여		20040318	20210719.0	163.0	48		18.066167	저체중
4	2021	8.559022	26		2. 읍지역			울산	여		20050519	20210322.0	157.0	45		18.256319	저체중
  • 이번엔 어플라이와 함수를 이용하여 [‘비만도2’]column을 추가해봅시다. 먼저 함수를 만들어줍시다.
def case_function(x):
    if x>22.9:
        return '과체중'
    elif x<18.5:
        return '저체중'
    else:
        return '정상'
  • 판다스의 apply()메소드를 사용하면 데이터프레임의 행 또는 열에 함수를 적용할 수 있습니다. axis=1이면 당연히 열에 적용되겠죠?
df['비만도2']=df['bmi'].apply(case_function)
df[:5]
학년도	최종가중치		strata	도시규모				시도	성별	생년월일		건강검진일	키		몸무게	bmi			비만도	비만도2
0	2021	23.328217	53		1. 대도시/중소도시	경북	여		20060123	20210819.0	160.0	61		23.828125	과체중	과체중
1	2021	46.369274	112		1. 대도시/중소도시	울산	남		20120816	20210420.0	128.0	32		19.531250	정상	정상
2	2021	124.663180	129		1. 대도시/중소도시	충북	여		20111222	20210715.0	132.0	27		5.495868	저체중	저체중
3	2021	29.561989	3		2. 읍지역			강원	여		20040318	20210719.0	163.0	48		18.066167	저체중	저체중
4	2021	8.559022	26		2. 읍지역			울산	여		20050519	20210322.0	157.0	45		18.256319	저체중	저체중
  • map이용할 수도 있습니다. 3개의 행만 가져와서 실습해보겠습니다. df3의 ‘비만도3’ 열을 생성하고, df3의 인덱스를 사용하여 a 딕셔너리를 매핑하여 값을 할당합니다.ㅊdf3의 인덱스에 해당하는 값들은 a 딕셔너리의 키로 사용되고, 매핑되는 값은 ‘비만도3’ 열에 할당됩니다.
df3=df[:3]
a={0:'과체중',1:'정상',2:'과체중'}
df3['비만도3']=df3.index.map(a)
df3
	학년도	최종가중치	strata	도시규모	시도		성별			생년월일		건강검진일	키		몸무게	bmi			비만도	비만도2	비만도3
0	2021	23.328217	53		1. 대도시/중소도시	경북	여		20060123	20210819.0	160.0	61		23.828125	과체중	과체중	과체중
1	2021	46.369274	112		1. 대도시/중소도시	울산	남		20120816	20210420.0	128.0	32		19.531250	정상	정상	정상
2	2021	124.663180	129		1. 대도시/중소도시	충북	여		20111222	20210715.0	132.0	27		15.495868	저체중	저체중	과체중	

7.실습

  • #실습이 끝난 df파일을 새로 저장하며 실습을 마무리하겠습니다.
df.to_csv('/Users/asd00/Desktop/Ch 03. 데이터 전처리/230526실습데이터.csv', index=False)
  • image

Categories:

Analytics   big-data   pandas