본문 바로가기

Python/Let's Get IT 파이썬 프로그래밍

[Let's Get IT 파이썬 프로그래밍] 8. 프로젝트 : 핫플레이스 인구 분석

728x90
반응형

  그동안 배웠던 내용을 집대성해 하나의 프로젝트를 완성하는 단계로 접어들었다. 'Let's Get IT 파이썬 프로그래밍'의 438~485 페이지에 해당한다. 이 카테고리의 모든 코드는 교재에 실린 코드를 보고 그대로 따라하거나 필자의 상상력을 가미해 각색한 것이라는 것을 밝혀둔다.


1. 환경 설정 및 데이터 전처리 

이번 과정은 꽤 귀찮은 작업이 많다. 외부 링크에서 파일을 설치하고, 데이터를 가다듬는 것이 대표적이다. 조금이나마 독자들의 수고를 덜어주고자 필요한 파일을 업로드하도록 하겠다. (파일 링크) 이 파일은 교재에 써있는 것처럼 서울 열린 데이터 광장에서 가져올 수 있다. 다만, 필자는 교재와 달리 작성일 기준 최신 데이터 (22.06 기준)를 사용하였음을 알린다.

 

# load library
import csv
from openpyxl import load_workbook as lw
import matplotlib as mp
import matplotlib.pyplot as plt
import datetime as dt
import numpy as np

 

code = lw("./data/행정동코드_매핑정보_20200325.xlsx", 
                        data_only = True) # 수식 제외 셀값만 가져오기

# 행정동코드 시트의 데이터 가져오기
code = code['행정동코드']

# 행과 열의 데이터 출력 
all_cell = []

# code 데이터를 행 단위로 가져온다.
for r in code.rows:
    r_value = [] # 빈 셀을 만든다
    
    # 행 단위로 가져온 데이터에서 셀값을 추출해 리스트에 담는다.
    for cell in r:
        r_value.append(cell.value)
    
    # 위의 과정을 반복하며 모든 데이터를 가져온다.
    all_cell.append(r_value)

# 컬럼을 제외한다.
code = all_cell[2:]
print(code)

 

교재에서는 csv로 다시 저장해 사용했으나 openpyxl 라이브러리로 xlsx 파일을 그대로 활용하였다. 전처리에 관련된 전체 코드는 아래와 같다. 행정동을 입력하는 단계에서 정확하지 않은 동 이름을 사용했을 때의 예외 처리를 넣어주면 보다 훌륭한 코드가 될 것이다.

 

# load library
import csv
from openpyxl import load_workbook as lw

# 생활인구 데이터
f = open("./ch11_data/LOCAL_PEOPLE_DONG_202206.csv", 
        encoding = 'utf8')
data = csv.reader(f)
next(data) # 컬럼명 제거
data = list(data)

# 행정동 코드 데이터
code = lw("./ch11_data/행정동코드_매핑정보_20200325.xlsx", 
                        data_only = True) # 수식 제외 셀값만 가져오기

# 행정동코드 시트의 데이터 가져오기
code = code['행정동코드']

# 행과 열의 데이터 출력 
all_cell = []

# code 데이터를 행 단위로 가져온다.
for r in code.rows:
    r_value = [] # 빈 셀을 만든다
    
    # 행 단위로 가져온 데이터에서 셀값을 추출해 리스트에 담는다.
    for cell in r:
        r_value.append(cell.value)
    
    # 위의 과정을 반복하며 모든 데이터를 가져온다.
    all_cell.append(r_value)

# 컬럼을 제외한다.
code = all_cell[2:]

# 행정동 데이터 자료형 변환
for row in data:
    for i in range(32):
        if i == 0 :
            row[i] = str(row[i])
        elif i <= 2 :
            row[i] = int(row[i])
        else :
            row[i] = float(row[i])

print("일시 자료형은?", type(data[0][0]))

# 코드 데이터 자료형 변환
for row in code:
    row[1] = int(row[1])

# 동 이름과 코드 연결            
dong = input("행정동을 입력하세요! => ")

for row in code:
    if row[-1] == dong:
        dong_code = row[1]

print(dong, "(" , dong_code , ")" + "을 분석합니다.")

 

2. 하위 목표 : 시간대별 인구 분석

# 초기값 0 지정, 24회 반복 (24시간이므로)
pop = [0 for i in range(24)]; pop

지금까지는 반복문을 여러 줄에 걸쳐 작성해왔다. 하지만 리스트 내포 (리스트 컴프리헨션, List Comprehension)을 쓰면 한 줄로 명료하게 나타낼 수 있다.

 

for row in data :
    if row[2] == dong_code:
        pop[row[1]] += row[3]
print(pop)

 

0이 24개 들어가는 초기값 리스트를 만들었고, 행정동 코드가 일치하는 경우의 행정동의 생활인구를 누적하는 반복문을 작성한다. 

 

pop = [i/31 for i in pop]; pop

 

한달 기준이므로 31로 나눠준다.

 

# 그래프 작성
plt.rc('font', family = "Malgun Gothic")
plt.title("%s 시간대별 평균인구" %dong)
plt.plot(range(24), pop, color = "darkblue")
plt.xticks(range(24), range(24))
plt.show()

필자가 조사한 연남동의 경우, 9~10시에는 생활인구가 가장 적고 19시 경에 가장 많아진다는 것을 알 수 있다. 맛집 등의 핫플레이스에 방문하는 사람이 저녁에 왔다가 주거지로 돌아가고, 연남동의 주민들이 돌아와 취침을 하기 때문에 22~23시의 떨어졌다 급상승하는 패턴이 나오는 것으로 보인다.

 

3. 하위 목표 : 타 지역과의 인구 비교

 

대치 1동과 대치 2동을 비교해보자!

 

# 동 이름과 코드 연결            
dong1 = input("행정동을 입력하세요! => ")

for row in code:
    if row[-1] == dong1:
        dong_code1 = row[1]

print(dong1, "(" , dong_code1 , ")" + "을 분석합니다.")

dong2 = input("비교할 행정동을 입력하세요! => ")

for row in code:
    if row[-1] == dong2:
        dong_code2 = row[1]

print(dong2, "(" , dong_code2 , ")" + "을 분석합니다.")

pop1 = [0 for i in range(24)]
pop2 = [0 for i in range(24)]

for row in data:
    if row[2] == dong_code1:
        pop1[row[1]] += row[3]
    elif row[2] == dong_code2:
        pop2[row[1]] += row[3]
        
pop1 = [p/31 for p in pop1]
pop2 = [p/31 for p in pop2]

plt.rc('font', family = "Malgun Gothic")
plt.title("%s과 %s의 시간대별 평균인구" %(dong1, dong2))
plt.plot(pop1, color = "darkseagreen", label = "%s" %dong1)
plt.plot(pop2, color = "sandybrown", label = "%s" %dong2)
plt.xticks(range(24), range(24))
plt.legend(loc = "best")
plt.show()

 

대치1동에 비해 대치2동이 인구가 많고, 변동폭이 크다는 것을 확인할 수 있다. 대치1동은 저녁 시간에 인구가 몰리는데 저녁 약속을 잡는 케이스가 많은 듯하다. 거주 인구는 밤에 인구가 줄어드는 것으로 보아 그다지 많지는 않아 보인다. 이는 대치2동도 마찬가지다. 그러나 대치2동은 오전부터 생활인구가 급상승하여 낮시간대가 피크로, 가장 붐비는 것으로 사료된다.

 


핫플레이스라는 제목이지만, 그냥 필자가 아무 동이나 골라서 진행하였기 때문에 다소 관련성이 떨어진다고 생각되는데 이에 대해 양해를 구한다. 제대로 하려면 인구 top10 정도를 추려서 해당 행정동끼리 비교를 했어야 할 것이다. 아, 참고로 하위 분석 2가지를 실었지만 나머지도 Github에 있으니 궁금하면 살펴보시길!

 

그리고 그래프가 나온 것으로 만족하지 말고, 데이터 분석이라는 테마에 걸맞게 자신만의 관점을 담아 정리해보는 것이 자신의 실력을 기르는 데도, 타인과의 대화를 이끌어가는 데도 도움이 되리라 생각한다.

728x90
반응형