4.2. 데이터프레임의 정리#
이 절에서는 데이터프레임을 정리할 떄 지주 사용되는 다음과 같은 내용을 살펴본다.
정렬(sorting)
열 지우기
행 지우기
행 인덱스 재구성
열이름 바꾸기
외부화일로 저장하기
import pandas as pd
4.2.1. 자료의 정리#
앞 절에서 살펴본 내용은 데이터의 일부분을 조건에 맞게 열과 행을 선택하여 필요한 데이터만 선택하는 작업이었다.
컴퓨터에서 사용할 수 있도록 데이터를 읽은 후에, 데이터프레임을 정렬하거나 열이름을 바꾸어 새로운 자료를 만들기 위한 전처리 작업을 한다.
자료를 주어진 규칙에 따라서 정렬하는(sorting) 작업은 분석 단계에서도 많이 사용하지만 자료를 처음 받고 살펴볼 때도 자주 사용한다. 초기 자료는 대부분 우리가 예상하지 못하는 오류나 결함을 가지고 있을 가능성이 있다. 빅데이터 시대에 자료를 눈으로 살펴보는 것이 자주 있는 일은 아니지만 자료의 일부분을 보면서 원하는 자료가 제대로 입력이 되있는지 간단하게 살펴보는 버릇은 매우 좋은 버릇이다.
최근에는 컴퓨터 프로그램에서 한글을 자유롭게 사용할 수 있게 되었지만 아직도 자료를 여러 개의 다른 프로그램으로 바꾸어 작업하는 경우 한글 때문에 호환이 자유롭게 안돼는 경우가 많다. 특히 순수한 자료가 아닌 프로그램 언어의 표현식, 인덱스, 열이름 등에 한글을 사용하면 문제를 일으킬 수 있다. 데이터프레임에서는 열이름이나 행인덱스에 한글을 사용할 수 있지만 영문으로 바꾸어야 하는 경우도 많다.
이제 데이터프레임을 원하는대로 정렬하고, 열과 행을 지우고, 열의 이름을 바꾸는 작업에 대하여 알아보자.
먼저, 예제로 사용될 자료를 살펴보자
4.2.2. 한국의 가구수#
최근 한국의 인구 동향이 급격하게 변화하고 있다. 특히 1인 가구 수의 증가가 우리의 생활에 많은 변화를 주고 있다. 이제 2015년부터 2020년까지 6년간 우리나라의 가구 분포를 비교하여 가구의 구성이 어떻게 변화했는지 살펴보자.
다음 자료는 통계청 국가통계포털 에서 받은 인구총조사(등록센서스) 자료이다. 데이터는 시도별로 6년의 가구수를 가구의 인원별로 나누어 놓은 자료이다.
데이터를 외부 CSV 화일에서 데이터프레임으로 일거 어려면 다음과 같은 read_csv()
함수를 사용한다.
encoding="cp949"
은 화일의 언어형식을 지정하는 선택 명령이다.cp949
는 MS Windows 에서 사용하는 한글의 언어형식이다.만약
cp949
를 사용하였을 때 한글이 깨져보이면utf-8
또는utf-8-sig
을 사용해 보자.언어형식은 컴퓨터(운영체제; MS Window, MacOS, Linux) 에 따라서 다를 수 있으므로
cp949
,utf-8
,utf-8-sig
중 잘 작동하는 하나를 선택한다.
url = "https://ilovedata.github.io/teaching/bigdata2/data/korea_house_data_01.csv"
house = pd.read_csv(url, encoding="CP949")
아래 house.head(10)
은 데이터프레임 house
의 처음 10개 행만을 출력하는 메소드이다. 아주 맣은 행을 가진 데이터프레임의 앞부부만 볼 때 유용하다. 유사한 방법으로 house.tail(5)
를 실행하면 어떤 결과가 나올까?
house.head(10)
시점 | 행정구역별(읍면동) | 일반가구_계 | 1인 | 2인 | 3인 | 4인 | 5인 | 6인 | 7인 이상 | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 2015 | 전국 | 19111030 | 5203440 | 4993818 | 4100979 | 3588931 | 940413 | 217474 | 65975 |
1 | 2015 | 서울특별시 | 3784490 | 1115744 | 930467 | 817440 | 701945 | 169436 | 38547 | 10911 |
2 | 2015 | 부산광역시 | 1335900 | 361749 | 366048 | 296742 | 238031 | 56971 | 12928 | 3431 |
3 | 2015 | 대구광역시 | 928528 | 239517 | 239824 | 208795 | 184258 | 44071 | 9582 | 2481 |
4 | 2015 | 인천광역시 | 1045417 | 243678 | 265079 | 245135 | 220538 | 55230 | 12253 | 3504 |
5 | 2015 | 광주광역시 | 567157 | 163577 | 137662 | 115701 | 109612 | 32199 | 6647 | 1759 |
6 | 2015 | 대전광역시 | 582504 | 169391 | 140603 | 122088 | 112055 | 30022 | 6489 | 1856 |
7 | 2015 | 울산광역시 | 423412 | 103551 | 104101 | 100230 | 90735 | 19914 | 3851 | 1030 |
8 | 2015 | 세종특별자치시 | 75219 | 21889 | 18010 | 15219 | 14560 | 4238 | 994 | 309 |
9 | 2015 | 경기도 | 4384742 | 1026471 | 1062222 | 1005330 | 971146 | 246638 | 56117 | 16818 |
4.2.3. 정렬#
먼저 데이터프레임의 행들을 지정된 열에 있는 자료의 순서대로 정렬하는 방법을 알아보자.
정렬은
sort_values()
메소드를 사용한다. 괄호 안에by=
을 사용하여 정렬항 열이름이나 열이름으로 구성된 리스트를 지정한다.정렬의 순서는 선택문
ascending=
을 사용하며 오름차순은ascending=True
으로, 내림차순은ascending=False
로 지정한다. 순서를 지정하지 않으면 오름차순이 적용된다.
이제 데이터프레임을 행정구역별(읍면동)
으로 정렬해보자. 강원도가 처음으로, 충청북도가 마지막으로 나타나는 것을 알 수 있다.
house.sort_values(by = '행정구역별(읍면동)')
시점 | 행정구역별(읍면동) | 일반가구_계 | 1인 | 2인 | 3인 | 4인 | 5인 | 6인 | 7인 이상 | |
---|---|---|---|---|---|---|---|---|---|---|
82 | 2019 | 강원도 | 633942 | 208857 | 200035 | 117416 | 79476 | 21560 | 5043 | 1555 |
100 | 2020 | 강원도 | 661039 | 231371 | 206755 | 117504 | 79073 | 20669 | 4409 | 1258 |
28 | 2016 | 강원도 | 616346 | 197917 | 180639 | 117408 | 86362 | 25441 | 6477 | 2102 |
64 | 2018 | 강원도 | 628484 | 206295 | 193105 | 117713 | 81241 | 22835 | 5522 | 1773 |
46 | 2017 | 강원도 | 620729 | 199645 | 187312 | 117912 | 83773 | 24178 | 6020 | 1889 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
101 | 2020 | 충청북도 | 678922 | 236208 | 198840 | 122347 | 91329 | 24143 | 4694 | 1361 |
65 | 2018 | 충청북도 | 640978 | 204109 | 183501 | 123042 | 94970 | 27286 | 6166 | 1904 |
83 | 2019 | 충청북도 | 654713 | 215196 | 191655 | 123239 | 91764 | 25674 | 5503 | 1682 |
11 | 2015 | 충청북도 | 601856 | 173598 | 167146 | 120634 | 100527 | 30110 | 7428 | 2413 |
47 | 2017 | 충청북도 | 629073 | 195186 | 176617 | 122463 | 97422 | 28487 | 6737 | 2161 |
108 rows × 10 columns
이제 행정구역별(읍면동)
별로, 시점
별로, 두 개의 열에 대하여 정렬해 보자
house.sort_values(by = [ '행정구역별(읍면동)', '시점'])
시점 | 행정구역별(읍면동) | 일반가구_계 | 1인 | 2인 | 3인 | 4인 | 5인 | 6인 | 7인 이상 | |
---|---|---|---|---|---|---|---|---|---|---|
10 | 2015 | 강원도 | 606117 | 189379 | 178470 | 116384 | 87182 | 25922 | 6567 | 2213 |
28 | 2016 | 강원도 | 616346 | 197917 | 180639 | 117408 | 86362 | 25441 | 6477 | 2102 |
46 | 2017 | 강원도 | 620729 | 199645 | 187312 | 117912 | 83773 | 24178 | 6020 | 1889 |
64 | 2018 | 강원도 | 628484 | 206295 | 193105 | 117713 | 81241 | 22835 | 5522 | 1773 |
82 | 2019 | 강원도 | 633942 | 208857 | 200035 | 117416 | 79476 | 21560 | 5043 | 1555 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
29 | 2016 | 충청북도 | 617914 | 187377 | 170184 | 121917 | 99555 | 29534 | 7075 | 2272 |
47 | 2017 | 충청북도 | 629073 | 195186 | 176617 | 122463 | 97422 | 28487 | 6737 | 2161 |
65 | 2018 | 충청북도 | 640978 | 204109 | 183501 | 123042 | 94970 | 27286 | 6166 | 1904 |
83 | 2019 | 충청북도 | 654713 | 215196 | 191655 | 123239 | 91764 | 25674 | 5503 | 1682 |
101 | 2020 | 충청북도 | 678922 | 236208 | 198840 | 122347 | 91329 | 24143 | 4694 | 1361 |
108 rows × 10 columns
2020년 가구수만 볼 수 있을까? 다음 표현식의 결과를 보자. 앞 절에서 배운 조건식을 이용한 슬라이싱을 사용하였다.
2020년만 선택한 후, 총 가구수를 이용하여 내림차순으로 정렬해 보자. 경기도가 가장 많은 가구수를 가진 도이다.
house[house['시점'] == 2020 ].sort_values(by = [ '일반가구_계'], ascending=False)
시점 | 행정구역별(읍면동) | 일반가구_계 | 1인 | 2인 | 3인 | 4인 | 5인 | 6인 | 7인 이상 | |
---|---|---|---|---|---|---|---|---|---|---|
90 | 2020 | 전국 | 20926710 | 6643354 | 5864525 | 4200629 | 3271315 | 761417 | 147172 | 38298 |
99 | 2020 | 경기도 | 5098431 | 1406010 | 1350139 | 1119823 | 951370 | 218173 | 42094 | 10822 |
91 | 2020 | 서울특별시 | 3982290 | 1390701 | 1033901 | 792690 | 602791 | 130122 | 25770 | 6315 |
92 | 2020 | 부산광역시 | 1405037 | 455207 | 411455 | 282233 | 203769 | 42608 | 7874 | 1891 |
106 | 2020 | 경상남도 | 1350155 | 417737 | 399700 | 270061 | 205658 | 46516 | 8410 | 2073 |
94 | 2020 | 인천광역시 | 1147200 | 324841 | 316387 | 251928 | 198528 | 44949 | 8440 | 2127 |
105 | 2020 | 경상북도 | 1131819 | 388791 | 363061 | 202539 | 137092 | 32174 | 6388 | 1774 |
93 | 2020 | 대구광역시 | 985816 | 304543 | 276237 | 205048 | 159654 | 33131 | 5976 | 1227 |
102 | 2020 | 충청남도 | 892222 | 304973 | 264909 | 159754 | 121589 | 32419 | 6618 | 1960 |
104 | 2020 | 전라남도 | 761518 | 256633 | 251506 | 131372 | 87883 | 26561 | 5727 | 1836 |
103 | 2020 | 전라북도 | 755575 | 255269 | 233334 | 134414 | 96907 | 27962 | 5920 | 1769 |
101 | 2020 | 충청북도 | 678922 | 236208 | 198840 | 122347 | 91329 | 24143 | 4694 | 1361 |
100 | 2020 | 강원도 | 661039 | 231371 | 206755 | 117504 | 79073 | 20669 | 4409 | 1258 |
96 | 2020 | 대전광역시 | 631208 | 228842 | 164795 | 116989 | 93698 | 21883 | 4034 | 967 |
95 | 2020 | 광주광역시 | 599217 | 193948 | 162403 | 115978 | 97323 | 24613 | 4011 | 941 |
97 | 2020 | 울산광역시 | 444087 | 122848 | 123591 | 99739 | 79489 | 15447 | 2398 | 575 |
107 | 2020 | 제주특별자치도 | 263068 | 81855 | 74308 | 49903 | 38747 | 13719 | 3380 | 1156 |
98 | 2020 | 세종특별자치시 | 139106 | 43577 | 33204 | 28307 | 26415 | 6328 | 1029 | 246 |
지금까지 여러 조합을 이용하여 데이터프레임 house
를 정렬을 했는데 원자료는 변했을까?
데이터프레임을 위와 같이 정렬해도 출력으로만 결과를 보여주고 원자료는 실제로 정렬되지 않는다.
house.head(10)
시점 | 행정구역별(읍면동) | 일반가구_계 | 1인 | 2인 | 3인 | 4인 | 5인 | 6인 | 7인 이상 | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 2015 | 전국 | 19111030 | 5203440 | 4993818 | 4100979 | 3588931 | 940413 | 217474 | 65975 |
1 | 2015 | 서울특별시 | 3784490 | 1115744 | 930467 | 817440 | 701945 | 169436 | 38547 | 10911 |
2 | 2015 | 부산광역시 | 1335900 | 361749 | 366048 | 296742 | 238031 | 56971 | 12928 | 3431 |
3 | 2015 | 대구광역시 | 928528 | 239517 | 239824 | 208795 | 184258 | 44071 | 9582 | 2481 |
4 | 2015 | 인천광역시 | 1045417 | 243678 | 265079 | 245135 | 220538 | 55230 | 12253 | 3504 |
5 | 2015 | 광주광역시 | 567157 | 163577 | 137662 | 115701 | 109612 | 32199 | 6647 | 1759 |
6 | 2015 | 대전광역시 | 582504 | 169391 | 140603 | 122088 | 112055 | 30022 | 6489 | 1856 |
7 | 2015 | 울산광역시 | 423412 | 103551 | 104101 | 100230 | 90735 | 19914 | 3851 | 1030 |
8 | 2015 | 세종특별자치시 | 75219 | 21889 | 18010 | 15219 | 14560 | 4238 | 994 | 309 |
9 | 2015 | 경기도 | 4384742 | 1026471 | 1062222 | 1005330 | 971146 | 246638 | 56117 | 16818 |
만약 정렬된 결과를 다른 이름으로 데이터프레임에 저장하면 어떻게 될까? 다른 데이터프레임으로 지정하면 정렬로 변한 결과가 적용되어 저장된다.
house_copy = house.sort_values(by = [ '행정구역별(읍면동)', '시점'])
house_copy.head(10)
시점 | 행정구역별(읍면동) | 일반가구_계 | 1인 | 2인 | 3인 | 4인 | 5인 | 6인 | 7인 이상 | |
---|---|---|---|---|---|---|---|---|---|---|
10 | 2015 | 강원도 | 606117 | 189379 | 178470 | 116384 | 87182 | 25922 | 6567 | 2213 |
28 | 2016 | 강원도 | 616346 | 197917 | 180639 | 117408 | 86362 | 25441 | 6477 | 2102 |
46 | 2017 | 강원도 | 620729 | 199645 | 187312 | 117912 | 83773 | 24178 | 6020 | 1889 |
64 | 2018 | 강원도 | 628484 | 206295 | 193105 | 117713 | 81241 | 22835 | 5522 | 1773 |
82 | 2019 | 강원도 | 633942 | 208857 | 200035 | 117416 | 79476 | 21560 | 5043 | 1555 |
100 | 2020 | 강원도 | 661039 | 231371 | 206755 | 117504 | 79073 | 20669 | 4409 | 1258 |
9 | 2015 | 경기도 | 4384742 | 1026471 | 1062222 | 1005330 | 971146 | 246638 | 56117 | 16818 |
27 | 2016 | 경기도 | 4484424 | 1067916 | 1091119 | 1033608 | 973096 | 246575 | 55612 | 16498 |
45 | 2017 | 경기도 | 4602950 | 1124541 | 1146712 | 1056797 | 966018 | 240634 | 53016 | 15232 |
63 | 2018 | 경기도 | 4751497 | 1197586 | 1213259 | 1084338 | 958729 | 234095 | 49527 | 13963 |
정렬한 자료를 유지하여 데이터프레임을 바꾸고 싶다면 메소드 sort_vaalues()
의 선택문으로 inplace = True
라고 지정해주면 된다.
물론 지정하지 않는 경우 inplace = False
가 자동적으로 적용된다.
이제 데이터프레임 house_sorted
를 년도로 정렬하고 그 결과를 유지하게 해보자.
house_copy.sort_values(by = [ '시점'], inplace= True)
house_copy.head(10)
시점 | 행정구역별(읍면동) | 일반가구_계 | 1인 | 2인 | 3인 | 4인 | 5인 | 6인 | 7인 이상 | |
---|---|---|---|---|---|---|---|---|---|---|
10 | 2015 | 강원도 | 606117 | 189379 | 178470 | 116384 | 87182 | 25922 | 6567 | 2213 |
6 | 2015 | 대전광역시 | 582504 | 169391 | 140603 | 122088 | 112055 | 30022 | 6489 | 1856 |
5 | 2015 | 광주광역시 | 567157 | 163577 | 137662 | 115701 | 109612 | 32199 | 6647 | 1759 |
11 | 2015 | 충청북도 | 601856 | 173598 | 167146 | 120634 | 100527 | 30110 | 7428 | 2413 |
2 | 2015 | 부산광역시 | 1335900 | 361749 | 366048 | 296742 | 238031 | 56971 | 12928 | 3431 |
17 | 2015 | 제주특별자치도 | 220369 | 58446 | 58302 | 43864 | 38308 | 15257 | 4378 | 1814 |
1 | 2015 | 서울특별시 | 3784490 | 1115744 | 930467 | 817440 | 701945 | 169436 | 38547 | 10911 |
15 | 2015 | 경상북도 | 1062724 | 322569 | 320498 | 207395 | 156364 | 42161 | 10360 | 3377 |
8 | 2015 | 세종특별자치시 | 75219 | 21889 | 18010 | 15219 | 14560 | 4238 | 994 | 309 |
7 | 2015 | 울산광역시 | 423412 | 103551 | 104101 | 100230 | 90735 | 19914 | 3851 | 1030 |
4.2.4. 행과 열 지우기#
처음 자료를 데이터프레임으로 만든 후에 특정한 행 또는 열을 제거해야 할 떄가 많다. 이제 행과 열을 지우는 방법을 알아보자.
행과 열을 지우는 작업은 슬라이싱과 다르다. 물론 슬라이싱으로 열과 행을 선택한 후에 새로운 데이터프레임에 저장하면 원하는 행과 열을 지운 결과를 얻는다. 이 절에서는 새로운 데이터프레임을 만들지 않고 주어진 데이터프레임에서 행과 열을 제거하는 방법을 배운다.
4.2.4.1. 열 지우기#
열을 지우는 일이 행을 지우는 것보다 수우니 먼저 열을 지우는 방법부터 알아보자.
이제 데이터프레임 house
에서 열 일반가구_계
를 지워보자. 열 일반가구_계
는 열 1인
부터 열 7인 이상
까지 모든 가구수를 더한 합계를 가지고 있다.
이렇게 다른 행들의 합계는 자료에 있는 것도 도움이 되자만 원하면 언제나 만들 수 있기 때문에 지워보자 (자료를 정리할 때 다른 행과 열들로 만들 수 있는 자료는 지워도 되지만 고유의 값을 가진 자료응 지워서는 안된다. 만약
행 1인
을 제거하면 어떻게 될까? ㅜㅜ)
열을 지우는 방법은 drop
메소드로 쉽게 할 수 있다.
columns =
에 삭제할 열이름을 리스트 형식으로 지정해 준다.선택문
inplace= True
는 데이터프레임house
의 내용을 변경한다.
주의: 선택문 inplace= True
를 사용할 떄 실수하면 데이터프레임을 복구할 수없으니 조심해서 사용하자. 이제 왜 선택문 inplace
가 있는지 생각해 보자. 변경된 내용을 새로운 데이터프레임에 저장하면 원래 자료는 그냥 변하지 않고 있으니 자료를 잃을 위험은 없다. 하지만 빅데이터를 다루는 경우 자료의 복사본을 계속 만들면 어떻게 될지 생각헤 보자.
house.drop(columns = ["일반가구_계"], inplace= True)
house
시점 | 행정구역별(읍면동) | 1인 | 2인 | 3인 | 4인 | 5인 | 6인 | 7인 이상 | |
---|---|---|---|---|---|---|---|---|---|
0 | 2015 | 전국 | 5203440 | 4993818 | 4100979 | 3588931 | 940413 | 217474 | 65975 |
1 | 2015 | 서울특별시 | 1115744 | 930467 | 817440 | 701945 | 169436 | 38547 | 10911 |
2 | 2015 | 부산광역시 | 361749 | 366048 | 296742 | 238031 | 56971 | 12928 | 3431 |
3 | 2015 | 대구광역시 | 239517 | 239824 | 208795 | 184258 | 44071 | 9582 | 2481 |
4 | 2015 | 인천광역시 | 243678 | 265079 | 245135 | 220538 | 55230 | 12253 | 3504 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
103 | 2020 | 전라북도 | 255269 | 233334 | 134414 | 96907 | 27962 | 5920 | 1769 |
104 | 2020 | 전라남도 | 256633 | 251506 | 131372 | 87883 | 26561 | 5727 | 1836 |
105 | 2020 | 경상북도 | 388791 | 363061 | 202539 | 137092 | 32174 | 6388 | 1774 |
106 | 2020 | 경상남도 | 417737 | 399700 | 270061 | 205658 | 46516 | 8410 | 2073 |
107 | 2020 | 제주특별자치도 | 81855 | 74308 | 49903 | 38747 | 13719 | 3380 | 1156 |
108 rows × 9 columns
4.2.4.2. 행 지우기#
데이터프레임 house
는 행정구역이 시도별로 자료가 구성되어 있다.
그런데 열 행정구역별(읍면동)
에 전국
을 포함하고 있다. 행정구역별이 아닌 전국에 대한 정보를 볼 수 있어 도움이 되지만 열을 구성하는 단위가 아니다. 자료를 만드는 경우 열의 구성요소가 아닌 내용이 포함되면 분석할 떄 문제가 생길 수 있다.
이제 열 행정구역별(읍면동)
의 값으로 전국
을 가지는 행을 지워보자.
다시 주의: 앞 절에서 배운대로 행정구역별(읍면동)
이 전국
이 아닌 행들만 슬라이싱 할 수 있다. 선택된 행들을 다른 이름의 데이터프레임으로 저정하면 되지만 슬라이싱은 선택만 할 뿐 데이터프레임 자체를 바꾸진 않는다.
조건에 따라서 행을 지우는 경우 drop
메소드를 사용할 수 있다.
이제 행정구역별(읍면동)
이 전국
인 행을 drop
메소드로 지우고 데이터프레임에 적용되게 해보자. 다음과 같은 순서로 처리할 수 있다.
먼저, 행정구역별(읍면동)
이 전국
인 데이터프레임을 만들고 해당하는 행의 위치(index,인덱스)를 추출한다. 아래와 같이 메소드 .index
를 사용하면 데이터프레임의 행의 위치를 나타내는 인덱스를 추출할 수 있다. 추출한 인덱스의 자료 형식은 Int64Index
이며 이는 행의 위치를 나타내는 형식이다.
index_for_delete = house[house["행정구역별(읍면동)"] == '전국'].index
이제 drop
메소드를 사용하여 행정구역별(읍면동)
이 전국
인 행을 지워보자.
index =
은 행에 대한 인덱스를 지정한다. 위에서 조건으로 만든index_for_delete
를 지정하면 해당하는 행이 제거된다.선택문
inplace= True
는 데이터프레임house
의 내용을 변경한다.
house.drop( index = index_for_delete, inplace= True )
house.head(20)
시점 | 행정구역별(읍면동) | 1인 | 2인 | 3인 | 4인 | 5인 | 6인 | 7인 이상 | |
---|---|---|---|---|---|---|---|---|---|
1 | 2015 | 서울특별시 | 1115744 | 930467 | 817440 | 701945 | 169436 | 38547 | 10911 |
2 | 2015 | 부산광역시 | 361749 | 366048 | 296742 | 238031 | 56971 | 12928 | 3431 |
3 | 2015 | 대구광역시 | 239517 | 239824 | 208795 | 184258 | 44071 | 9582 | 2481 |
4 | 2015 | 인천광역시 | 243678 | 265079 | 245135 | 220538 | 55230 | 12253 | 3504 |
5 | 2015 | 광주광역시 | 163577 | 137662 | 115701 | 109612 | 32199 | 6647 | 1759 |
6 | 2015 | 대전광역시 | 169391 | 140603 | 122088 | 112055 | 30022 | 6489 | 1856 |
7 | 2015 | 울산광역시 | 103551 | 104101 | 100230 | 90735 | 19914 | 3851 | 1030 |
8 | 2015 | 세종특별자치시 | 21889 | 18010 | 15219 | 14560 | 4238 | 994 | 309 |
9 | 2015 | 경기도 | 1026471 | 1062222 | 1005330 | 971146 | 246638 | 56117 | 16818 |
10 | 2015 | 강원도 | 189379 | 178470 | 116384 | 87182 | 25922 | 6567 | 2213 |
11 | 2015 | 충청북도 | 173598 | 167146 | 120634 | 100527 | 30110 | 7428 | 2413 |
12 | 2015 | 충청남도 | 234513 | 226658 | 153585 | 128382 | 39334 | 10031 | 3682 |
13 | 2015 | 전라북도 | 213750 | 209008 | 135856 | 110132 | 36433 | 9038 | 3094 |
14 | 2015 | 전라남도 | 218864 | 227975 | 131454 | 96940 | 33229 | 8881 | 3269 |
15 | 2015 | 경상북도 | 322569 | 320498 | 207395 | 156364 | 42161 | 10360 | 3377 |
16 | 2015 | 경상남도 | 346754 | 341745 | 265127 | 228216 | 59248 | 13383 | 4014 |
17 | 2015 | 제주특별자치도 | 58446 | 58302 | 43864 | 38308 | 15257 | 4378 | 1814 |
19 | 2016 | 서울특별시 | 1138860 | 931262 | 816946 | 686469 | 163555 | 37153 | 10460 |
20 | 2016 | 부산광역시 | 372412 | 370623 | 296627 | 233160 | 55496 | 12460 | 3392 |
21 | 2016 | 대구광역시 | 247444 | 242931 | 209737 | 181468 | 42748 | 9114 | 2311 |
이제 우리는 연도별, 시도별 가구구성 자료를 필요없는 행과 열을 삭제하여 정리하였다.
그런데 바로 위에 나타난 데이터프레임 house
를 보면 행을 나타나는 인덱스에 0
과 18
이 나타나지 않는다. 이러한 이유는
지워진 행에 대한 인덱스가 같이 없어진 것이다. 즉, 행을 지우는 경우(그리고 정령을 하는 경우도) 자동적으로 행의 인덱스가 0부터 다시 구성되지 않는다.
이제 완성된 데이터프레임의 행 인덱스를 0부터 시작에서 빠진 수없이 다시 구성해 보자.
reset_index
메소드를 다음과 같이 적용하면 행 인덱스가 0부터 차례대로 구성된다.
drop=True
는 행 인덱스를 재구성 할 때 인덱스를 나타내는 새로운 열을 만들지 말라는 명령이다. 만약drop=Fase
로 하면 열이름이index
인 새로운 열이 추가된다.
house.reset_index(drop=True, inplace=True)
house.head(20)
시점 | 행정구역별(읍면동) | 1인 | 2인 | 3인 | 4인 | 5인 | 6인 | 7인 이상 | |
---|---|---|---|---|---|---|---|---|---|
0 | 2015 | 서울특별시 | 1115744 | 930467 | 817440 | 701945 | 169436 | 38547 | 10911 |
1 | 2015 | 부산광역시 | 361749 | 366048 | 296742 | 238031 | 56971 | 12928 | 3431 |
2 | 2015 | 대구광역시 | 239517 | 239824 | 208795 | 184258 | 44071 | 9582 | 2481 |
3 | 2015 | 인천광역시 | 243678 | 265079 | 245135 | 220538 | 55230 | 12253 | 3504 |
4 | 2015 | 광주광역시 | 163577 | 137662 | 115701 | 109612 | 32199 | 6647 | 1759 |
5 | 2015 | 대전광역시 | 169391 | 140603 | 122088 | 112055 | 30022 | 6489 | 1856 |
6 | 2015 | 울산광역시 | 103551 | 104101 | 100230 | 90735 | 19914 | 3851 | 1030 |
7 | 2015 | 세종특별자치시 | 21889 | 18010 | 15219 | 14560 | 4238 | 994 | 309 |
8 | 2015 | 경기도 | 1026471 | 1062222 | 1005330 | 971146 | 246638 | 56117 | 16818 |
9 | 2015 | 강원도 | 189379 | 178470 | 116384 | 87182 | 25922 | 6567 | 2213 |
10 | 2015 | 충청북도 | 173598 | 167146 | 120634 | 100527 | 30110 | 7428 | 2413 |
11 | 2015 | 충청남도 | 234513 | 226658 | 153585 | 128382 | 39334 | 10031 | 3682 |
12 | 2015 | 전라북도 | 213750 | 209008 | 135856 | 110132 | 36433 | 9038 | 3094 |
13 | 2015 | 전라남도 | 218864 | 227975 | 131454 | 96940 | 33229 | 8881 | 3269 |
14 | 2015 | 경상북도 | 322569 | 320498 | 207395 | 156364 | 42161 | 10360 | 3377 |
15 | 2015 | 경상남도 | 346754 | 341745 | 265127 | 228216 | 59248 | 13383 | 4014 |
16 | 2015 | 제주특별자치도 | 58446 | 58302 | 43864 | 38308 | 15257 | 4378 | 1814 |
17 | 2016 | 서울특별시 | 1138860 | 931262 | 816946 | 686469 | 163555 | 37153 | 10460 |
18 | 2016 | 부산광역시 | 372412 | 370623 | 296627 | 233160 | 55496 | 12460 | 3392 |
19 | 2016 | 대구광역시 | 247444 | 242931 | 209737 | 181468 | 42748 | 9114 | 2311 |
4.2.5. 열이름 바꾸기#
자료를 정리할 때 열이름을 바꾸는 경우가 매우 흔하다.
열이름의 길이를 줄이거나, 열이름에 대한 새로운 규칙을 적용하거나, 개인의 취향을 사용하거나… 열이름을 변경해야할 일이 자주 일어난다.
데이터프레임 house
의 열이름을 영문으로 바꾸어 보자.
열이름을 바꿀 떄는 rename()
메소드를 사용한다. 다음과 같이 열이름을 바꾸어 보자.
columns =
에 사전 형식((Dictionary type)으로 새로운 열의 이름을 지정한다.열이름은 앞에서 잠깐 나온 사전(Dictionary) 형식이다. 다음과 같은 규칙을 가진다.
내요은
{...}
안에 넣는다.원래 열이름과 새로운 열이름의 문자열을 각각
:
의 왼쪽과 오른쪽에 놓는다.다른 열이름을 컴마
,
로 구분한다.
inplace=True
를 선택해여 열이름 변경이 데이터프레임에 적용된다.
house.rename( columns={
"시점" : "year", "행정구역별(읍면동)" : "region",
"1인" : "p1", "2인" : "p2", "3인" : "p3", "4인" : "p4",
"5인" : "p5", "6인" : "p6", "7인 이상" : "p7plus"},
inplace=True)
house
year | region | p1 | p2 | p3 | p4 | p5 | p6 | p7plus | |
---|---|---|---|---|---|---|---|---|---|
0 | 2015 | 서울특별시 | 1115744 | 930467 | 817440 | 701945 | 169436 | 38547 | 10911 |
1 | 2015 | 부산광역시 | 361749 | 366048 | 296742 | 238031 | 56971 | 12928 | 3431 |
2 | 2015 | 대구광역시 | 239517 | 239824 | 208795 | 184258 | 44071 | 9582 | 2481 |
3 | 2015 | 인천광역시 | 243678 | 265079 | 245135 | 220538 | 55230 | 12253 | 3504 |
4 | 2015 | 광주광역시 | 163577 | 137662 | 115701 | 109612 | 32199 | 6647 | 1759 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
97 | 2020 | 전라북도 | 255269 | 233334 | 134414 | 96907 | 27962 | 5920 | 1769 |
98 | 2020 | 전라남도 | 256633 | 251506 | 131372 | 87883 | 26561 | 5727 | 1836 |
99 | 2020 | 경상북도 | 388791 | 363061 | 202539 | 137092 | 32174 | 6388 | 1774 |
100 | 2020 | 경상남도 | 417737 | 399700 | 270061 | 205658 | 46516 | 8410 | 2073 |
101 | 2020 | 제주특별자치도 | 81855 | 74308 | 49903 | 38747 | 13719 | 3380 | 1156 |
102 rows × 9 columns
위에서 열이름을 모두 바꾸는 코드와 동일한 작업을 새로운 이름을 가진 리스트로 다음과 같이 할 수 있다.
예를 들어 위에서 영문으로 변경한 마지막 열의 이름을 p7plus
에서 p7_and_more
로 다음과 같이 바꾸어보자.
house.columns = ["year", "region", "p1", "p2", "p2", "p4", "p5", "p6", "p7_and_more"]
house.head(10)
year | region | p1 | p2 | p2 | p4 | p5 | p6 | p7_and_more | |
---|---|---|---|---|---|---|---|---|---|
0 | 2015 | 서울특별시 | 1115744 | 930467 | 817440 | 701945 | 169436 | 38547 | 10911 |
1 | 2015 | 부산광역시 | 361749 | 366048 | 296742 | 238031 | 56971 | 12928 | 3431 |
2 | 2015 | 대구광역시 | 239517 | 239824 | 208795 | 184258 | 44071 | 9582 | 2481 |
3 | 2015 | 인천광역시 | 243678 | 265079 | 245135 | 220538 | 55230 | 12253 | 3504 |
4 | 2015 | 광주광역시 | 163577 | 137662 | 115701 | 109612 | 32199 | 6647 | 1759 |
5 | 2015 | 대전광역시 | 169391 | 140603 | 122088 | 112055 | 30022 | 6489 | 1856 |
6 | 2015 | 울산광역시 | 103551 | 104101 | 100230 | 90735 | 19914 | 3851 | 1030 |
7 | 2015 | 세종특별자치시 | 21889 | 18010 | 15219 | 14560 | 4238 | 994 | 309 |
8 | 2015 | 경기도 | 1026471 | 1062222 | 1005330 | 971146 | 246638 | 56117 | 16818 |
9 | 2015 | 강원도 | 189379 | 178470 | 116384 | 87182 | 25922 | 6567 | 2213 |
데이터프레임 뒤에 .columns
를 붙이면 열이름을 볼 수 있다. 형식은 행의 위치를 나타내내는 인덱스(Index) 형식이다.
house.columns
Index(['year', 'region', 'p1', 'p2', 'p2', 'p4', 'p5', 'p6', 'p7_and_more'], dtype='object')
4.2.6. 외부화일로 저장하기#
정리된 데이터프레임은 외부화일로 저장하여 보관하는 것이 좋다.
물론 위에서 사용한 모든 명령어들을 모아놓으면 변경된 자료를 받아도 큰 문제없이 자료를 다시 정리할 수 있다. 만약 엑셀과 같은 앱(app)을 사용한다면 모든 과정을 수작업으로 다시 수행햐야 하는 어려움이 있다. 이것이 우리가 컴퓨터 프로그램을 배워야 하는 이유 중에 하나이다. 파이썬과 같은 컴퓨터 언어을 이용하면 일연의 복잡한 작업을 자동적으로 다시 반복할 수 있다.
데이터프레임을 CSV 화일로 저장하는 경우 각각 다음과 같이 to_csv()
메소드를 사용하면 된다.
sep=','
는 데이터의 구분자를 지정해 준다.header=True
는 CSV 화일의 첫 행에 열이름을 만들어 준다.index= True
는 행의 인덱스를 새로운 열로 추가해 준다.encoding = 'utf-8-sig'
는 저장되는 화일의 언어코드 형식을utf-8-sig
으로 지정한다화일의 언어코드 형식은 사용하는 컴퓨터(운영체제)에 따라 다르기 떄문에
utf-8
,utf-8-sig
,cp949
에서 작동하는 형식을 선택한다.
house.to_csv("/Users/ylee19067/Dropbox/project/teaching/bigdata/textbook/test/house_final.csv",
sep=',', header=True, index= False, encoding = 'utf-8-sig')
4.2.7. 요약#
데이터프레임을…
정렬할 때는
sort_values()
메소드를 사용한다.열 또는 행을 제거할 때
drop()
메소드를 사용한다.열이름을 바꿀 때는
rename()
메소드를 사용한다.행의 인덱스를 재구성하는 경우
reset_index()
를 이용한다.변경된 내용을 데이터프레임에 적용하려면
inplace = True
선택문을 사용한다.