Python

인구이동통계 빅데이터 파이썬으로 분석하기_2 (데이터 조회 및 분석)

범준킴 2023. 5. 24. 10:29
반응형

- 준비 사항

: 파이참 설치! (참고 : https://www.jetbrains.com/ko-kr/pycharm/download/#section=windows)

 

PyCharm 다운로드: JetBrains가 만든 전문 개발자용 Python IDE

 

www.jetbrains.com

: 파이썬 설치! (참고 : https://www.python.org/downloads/)

 

Download Python

The official home of the Python Programming Language

www.python.org

 

- 파이썬과 파이참 설치, 인구이동통계 데이터 다운로드 모두 완료가 되었다면 데이터 분석 준비 끝

0. 데이터 불러오기

import pandas as pd

df1 = pd.read_csv("C:/Users/Seo/Downloads/인구관련연간자료_20230519_18672_데이터/2022_인구관련연간자료_20230519_18672.csv")
df1.columns = ["전입행정구역_시도코드", "전입행정구역_시군구코드", "전입행정구역_읍면동코드", "전입연도", "전입월", "전입일", "전출행정구역_시도코드", "전출행정구역_시군구코드", "전출행정구역_읍면동코드", "전입사유코드", "전입자1_세대주관계코드", "전입자1_만연령", "전입자1_성별코드", "전입자2_세대주관계코드", "전입자2_만연령", "전입자2_성별코드", "전입자3_세대주관계코드", "전입자3_만연령", "전입자3_성별코드", "전입자4_세대주관계코드", "전입자4_만연령", "전입자4_성별코드", "전입자5_세대주관계코드", "전입자5_만연령", "전입자5_성별코드", "전입자6_세대주관계코드", "전입자6_만연령", "전입자6_성별코드", "전입자7_세대주관계코드", "전입자7_만연령", "전입자7_성별코드", "전입자8_세대주관계코드", "전입자8_만연령", "전입자8_성별코드", "전입자9_세대주관계코드", "전입자9_만연령", "전입자9_성별코드", "전입자10_세대주관계코드", "전입자10_만연령", "전입자10_성별코드", "일련번호"]
df1.info()
df1.head()

pandas 패키지를 이용하여 데이터를 불러온다.

별도의 인코딩 설정 없이 가능한 것으로 보아 인코딩은 UTF-8이다.

header 설정 없이 데이터를 불러온 뒤, 컬럼을 설정해준다. 

1부에서 살펴볼 수 있는 데이터 포맷 보기를 활용하여, 컬럼을 설정해준다.

df1.info() 명령을 통해 컬럼의 자료형과 컬렴명이 잘 들어갔는지 확인할 수 있다.

df1.head() 명령을 통해 해당 데이터의 최상단 5개 행을 볼 수 있고, 이를 통해 데이터가 잘 불러와졌는지 확인할 수 있다.

df1.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 5397095 entries, 0 to 5397094
Data columns (total 41 columns):
 #   Column         Dtype  
---  ------         -----  
 0   전입행정구역_시도코드    int64  
 1   전입행정구역_시군구코드   int64  
 2   전입행정구역_읍면동코드   int64  
 3   전입연도           int64  
 4   전입월            int64  
 5   전입일            int64  
 6   전출행정구역_시도코드    int64  
 7   전출행정구역_시군구코드   int64  
 8   전출행정구역_읍면동코드   int64  
 9   전입사유코드         int64  
 10  전입자1_세대주관계코드   int64  
 11  전입자1_만연령       int64  
 12  전입자1_성별코드      int64  
 13  전입자2_세대주관계코드   float64
 14  전입자2_만연령       float64
 15  전입자2_성별코드      float64
 16  전입자3_세대주관계코드   float64
 17  전입자3_만연령       float64
 18  전입자3_성별코드      float64
 19  전입자4_세대주관계코드   float64
 20  전입자4_만연령       float64
 21  전입자4_성별코드      float64
 22  전입자5_세대주관계코드   float64
 23  전입자5_만연령       float64
 24  전입자5_성별코드      float64
 25  전입자6_세대주관계코드   float64
 26  전입자6_만연령       float64
 27  전입자6_성별코드      float64
 28  전입자7_세대주관계코드   float64
 29  전입자7_만연령       float64
 30  전입자7_성별코드      float64
 31  전입자8_세대주관계코드   float64
 32  전입자8_만연령       float64
 33  전입자8_성별코드      float64
 34  전입자9_세대주관계코드   float64
 35  전입자9_만연령       float64
 36  전입자9_성별코드      float64
 37  전입자10_세대주관계코드  float64
 38  전입자10_만연령      float64
 39  전입자10_성별코드     float64
 40  일련번호           int64  
dtypes: float64(27), int64(14)
memory usage: 1.6 GB
df1.head()
   전입행정구역_시도코드  전입행정구역_시군구코드  전입행정구역_읍면동코드  ...  전입자10_만연령  전입자10_성별코드  일련번호
0           11           110         51500  ...        NaN         NaN     2
1           11           110         51500  ...        NaN         NaN     3
2           11           110         51500  ...        NaN         NaN     1
3           11           110         51500  ...        NaN         NaN     5
4           11           110         51500  ...        NaN         NaN     6
[5 rows x 41 columns]

 

살펴보기 전에 시도, 시군구, 읍면동이 모두 코드로 이루어져 있는데 우리는 알아보기 쉽게하기 위해서 모두 이름으로 바꾸어서 작업하자.

 

1. 시도, 시군구, 읍면동 코드를 시도, 시군구, 읍면동 명으로 바꾸기

- 행정구역코드집을 활용하여 data join 진행

 

법정동코드목록조회 - 행정표준코드관리시스템

정상적으로 로그아웃하지 않았거나, 동일 사용자가 로그인한 상태입니다. 강제로 로그인 하시겠습니까? (강제 로그인 시 다시 로그인을 하셔야 합니다.)

www.code.go.kr

>> 해당 링크에서 법정동코드 전체자료를 다운로드 받는다.

- 법정동코드와 법정동명 확인

name1 = pd.read_csv("C:/Users/Seo/Downloads/법정동코드 전체자료.txt", encoding="cp949", sep="\t")
name1.info()
name1.head()

※ 인코딩과 구분자에 유의하자.(tab = |t)

name1.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 46342 entries, 0 to 46341
Data columns (total 3 columns):
 #   Column  Non-Null Count  Dtype 
---  ------  --------------  ----- 
 0   법정동코드   46342 non-null  int64 
 1   법정동명    46342 non-null  object
 2   폐지여부    46342 non-null  object
dtypes: int64(1), object(2)
memory usage: 1.1+ MB
name1.head()
        법정동코드           법정동명 폐지여부
0  1100000000          서울특별시   존재
1  1111000000      서울특별시 종로구   존재
2  1111010100  서울특별시 종로구 청운동   존재
3  1111010200  서울특별시 종로구 신교동   존재
4  1111010300  서울특별시 종로구 궁정동   존재

 

- 폐지여부에서 존재하는 법정동만 사용하여 데이터를 분석해야하기 때문에 존재하는 법정동만 남겨놓는다.

name1 = pd.read_csv("C:/Users/Seo/Downloads/법정동코드 전체자료.txt", encoding="cp949", sep="\t")
name1.info()
name1.head()
name2 = name1[name1["폐지여부"] == "존재"]

>> 이 데이터는 잠시 대기하고 이후에 나올 분석과정에서 JOIN하도록 하자

 

여기서부터 크게 2가지 케이스로 나뉠 수 있다.

전출입 "건수"를 기준으로 분석하는 경우와 전출입"인구"를 기준으로 분석하는 경우.

 

2. 전출입건수 기준 분석

- 전입건수를 확인할 수 있는 컬럼은 별도로 존재하지 않기 때문에 전출입 정보를 담고있는 행(row)개수를 세어서 확인

- 전입자 정보를 사용하지 않기 때문에 편의를 위해 10번 컬럼(전입자1_세대주관계코드) 이하를 삭제하고 진행한다.

import pandas as pd

df1 = pd.read_csv("C:/Users/Seo/Downloads/인구관련연간자료_20230519_18672_데이터/2022_인구관련연간자료_20230519_18672.csv")
df1.columns = ["전입행정구역_시도코드", "전입행정구역_시군구코드", "전입행정구역_읍면동코드", "전입연도", "전입월", "전입일", "전출행정구역_시도코드", "전출행정구역_시군구코드", "전출행정구역_읍면동코드", "전입사유코드", "전입자1_세대주관계코드", "전입자1_만연령", "전입자1_성별코드", "전입자2_세대주관계코드", "전입자2_만연령", "전입자2_성별코드", "전입자3_세대주관계코드", "전입자3_만연령", "전입자3_성별코드", "전입자4_세대주관계코드", "전입자4_만연령", "전입자4_성별코드", "전입자5_세대주관계코드", "전입자5_만연령", "전입자5_성별코드", "전입자6_세대주관계코드", "전입자6_만연령", "전입자6_성별코드", "전입자7_세대주관계코드", "전입자7_만연령", "전입자7_성별코드", "전입자8_세대주관계코드", "전입자8_만연령", "전입자8_성별코드", "전입자9_세대주관계코드", "전입자9_만연령", "전입자9_성별코드", "전입자10_세대주관계코드", "전입자10_만연령", "전입자10_성별코드", "일련번호"]

df2 = df1.drop(["전입자1_세대주관계코드", "전입자1_만연령", "전입자1_성별코드", "전입자2_세대주관계코드", "전입자2_만연령", "전입자2_성별코드", "전입자3_세대주관계코드", "전입자3_만연령", "전입자3_성별코드", "전입자4_세대주관계코드", "전입자4_만연령", "전입자4_성별코드", "전입자5_세대주관계코드", "전입자5_만연령", "전입자5_성별코드", "전입자6_세대주관계코드", "전입자6_만연령", "전입자6_성별코드", "전입자7_세대주관계코드", "전입자7_만연령", "전입자7_성별코드", "전입자8_세대주관계코드", "전입자8_만연령", "전입자8_성별코드", "전입자9_세대주관계코드", "전입자9_만연령", "전입자9_성별코드", "전입자10_세대주관계코드", "전입자10_만연령", "전입자10_성별코드", "일련번호"], axis=1)
df2.info()
df2.head()

drop을 활용하여 필요없는 컬럼을 모두 삭제하였다.

※ drop 사용법 : 데이터프레임_이름.drop(["삭제하고싶은_컬럼_이름_1", "삭제하고싶은_컬럼_이름_2"], axis=1)

현재 시도코드, 시군구코드, 읍면동코드 3가지 컬럼으로  데이터가 나뉘었는데, 이를 합쳐주고 위에서 작성해놓았던 법정동명을 JOIN해보자

먼저 3가지 컬럼을 법정동코드로 병합하기 위해 int 타입의 컬럼을 str타입의 컬럼으로 변경시켜주자

그리고 법정동코드형태와 같은 형태로 만들기 위해 병합도 진행해주자

df2["전입행정구역_시도코드"] = df2["전입행정구역_시도코드"].astype(str)
df2["전입행정구역_시군구코드"] = df2["전입행정구역_시군구코드"].astype(str)
df2["전입행정구역_읍면동코드"] = df2["전입행정구역_읍면동코드"].astype(str)
df2["전입_법정동코드"] = df2["전입행정구역_시도코드"] + df2["전입행정구역_시군구코드"] + df2["전입행정구역_읍면동코드"]

df2["전출행정구역_시도코드"] = df2["전출행정구역_시도코드"].astype(str)
df2["전출행정구역_시군구코드"] = df2["전출행정구역_시군구코드"].astype(str)
df2["전출행정구역_읍면동코드"] = df2["전출행정구역_읍면동코드"].astype(str)
df2["전출_법정동코드"] = df2["전출행정구역_시도코드"] + df2["전출행정구역_시군구코드"] + df2["전출행정구역_읍면동코드"]

이제 데이터 조인을 위한 준비가 끝났다.

pd.merge를 활용하여 데이터 조인을 하고 drop을 활용하여 필요없는 컬럼까지 삭제해보자

join1 = pd.merge(left = df2, right = name2, left_on = "전입_법정동코드", right_on = "법정동코드")
join1["전입_법정동명"] = join1["법정동명"]
join1  = join1.drop(["법정동코드", "법정동명", "폐지여부"], axis=1)

join2 = pd.merge(left = join1, right = name2, left_on = "전출_법정동코드", right_on = "법정동코드")
join2["전출_법정동명"] = join2["법정동명"]
join2  = join2.drop(["법정동코드", "법정동명", "폐지여부"], axis=1)

join3 = join2.drop(["전입행정구역_시도코드", "전입행정구역_시군구코드", "전입행정구역_읍면동코드", "전출행정구역_시도코드", "전출행정구역_시군구코드", "전출행정구역_읍면동코드"], axis=1)

결과물 join3의 컬럼구조와 head를 보고 잘 되었는지 확인하자

join3.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 459047 entries, 0 to 459046
Data columns (total 8 columns):
 #   Column    Non-Null Count   Dtype 
---  ------    --------------   ----- 
 0   전입연도      459047 non-null  int64 
 1   전입월       459047 non-null  int64 
 2   전입일       459047 non-null  int64 
 3   전입사유코드    459047 non-null  int64 
 4   전입_법정동코드  459047 non-null  object
 5   전출_법정동코드  459047 non-null  object
 6   전입_법정동명   459047 non-null  object
 7   전출_법정동명   459047 non-null  object
dtypes: int64(4), object(4)
memory usage: 31.5+ MB
join3.head()
   전입연도  전입월  전입일  전입사유코드    전입_법정동코드    전출_법정동코드        전입_법정동명        전출_법정동명
0  2022    1    3       2  2671025000  2671025000  부산광역시 기장군 기장읍  부산광역시 기장군 기장읍
1  2022    1    3       2  2671025000  2671025000  부산광역시 기장군 기장읍  부산광역시 기장군 기장읍
2  2022    1    3       2  2671025000  2671025000  부산광역시 기장군 기장읍  부산광역시 기장군 기장읍
3  2022    1    3       2  2671025000  2671025000  부산광역시 기장군 기장읍  부산광역시 기장군 기장읍
4  2022    1    3       2  2671025000  2671025000  부산광역시 기장군 기장읍  부산광역시 기장군 기장읍

>>good

이제 pd.pivot_table 기능을 활용하여 읍면동 별 통계를 내어보자

# ------------------ pivot_table 레퍼런스-----------------------------------------
#  pdf1 = pd.pivot_table(데이터프레임,                # 피벗할 데이터프레임
#  index = ['컬럼명1', '컬럼명2'],                           # 행 위치에 들어갈 열
#  columns = ['컬럼명3'],                                      # 열 위치에 들어갈 열
#  values = ['컬럼명4', '컬럼명5'],                         # 데이터로 사용할 열
#  aggfunc = ['count', 'mean'])                              # 데이터 집계함수
# ------------------ pivot_table 레퍼런스-----------------------------------------

엑셀에 있는 피벗테이블의 기능과 동일하니 해당 데이터를 원하는 방식대로 가공하여 통계를 작성할 수 있다.

pdf1 = pd.pivot_table(join3, index="전입_법정동명", columns="전출_법정동명", values="전입연도", aggfunc="count")

pdf1.head()


전출_법정동명      강원도 강릉시 강동면  강원도 강릉시 구정면  ...  충청북도 충주시 주덕읍  충청북도 충주시 중앙탑면
전입_법정동명                                ...                             
강원도 강릉시 강동면         70.0          5.0  ...           NaN            NaN
강원도 강릉시 구정면          9.0         47.0  ...           NaN            NaN
강원도 강릉시 사천면          2.0          1.0  ...           NaN            NaN
강원도 강릉시 성산면          4.0          9.0  ...           NaN            NaN
강원도 강릉시 연곡면          2.0          4.0  ...           NaN            NaN
[5 rows x 1403 columns]

>> 각 읍면동별 전출입 건수를 matrix 형태로 만들어서 해당 읍면동에서 가장 많이 전출을 간 읍면동을 찾거나, 더 단순화하여 읍면동별 전출건수, 전입건수를 count할 수 있을 것이다.

 

3부에서는 2부의 소스들을 활용하여 전출입인구수를 활용한 통계를 작성해보도록 하겠다.

 

끄읕

반응형