본문 바로가기
프로그래밍언어/Python

[Python] : Jupyter Notebook을 활용한 데이터 분석

by 오주현 2021. 11. 24.
반응형
서울시 CCTV 현황 분석

 

import pandas as pd

pandas 모듈을 통해 SCV 파일과 엑셀 파일을 쉽게 읽을 수 있습니다.

 

CCTV_Seoul = pd.read_csv('c:/anaconda3/test/CCTV_in_Seoul.csv', encoding='utf-8')
CCTV_Seoul.head(4)

경로에 실습 파일을 넣어주고 읽어줍니다.

 

판다스 모듈에서 CSV 파일을 읽어주는 명령어는 read_csv입니다.

 

한글 사용을 위해서 인코딩을 UTF-8로 설정해 줬습니다.

 

CCTV_Seoul.columns

판다스 데이터는 제일 첫 줄에 보이는 것이 해당하는 열을 대표하는 일종의 제목이라고 합니다.

 

CCTV_Seoul.columns[0]

제목 줄의 첫 번째 값을 반환할 수 있습니다.

 

CCTV_Seoul.rename(columns={CCTV_Seoul.columns[0] : '구별'}, inplace=True)
CCTV_Seoul.head()

기관명을 구별로 바꿔줬습니다. 

 

이렇게 이름을 바꿔주는 명령어는 rename을 사용합니다.

 

inplace=True는 실제 CCTV_Seoul이라는 변수의 내용을 갱신하라는 의미입니다.

 

pop_Seoul = pd.read_excel('c:/anaconda3/test/population_in_Seoul.xls',
                          header = 2,
                          usecols = 'B, D, G, J, N',
                          encoding = 'utf-8')
pop_Seoul.head()

엑셀 파일을 읽는 명령어는 read_excel입니다.

 

첫 세 줄이 열의 제목처럼 되어 있어서 세 번째 줄부터 읽으라고 header=2라는 옵션을 사용했습니다.

 

B, D, G, J, N 열만 읽도록 usecols= 'B, D, G, J, N' 옵션을 사용했습니다.

 

pop_Seoul.rename(columns={pop_Seoul.columns[0] : '구별',
                          pop_Seoul.columns[1] : '인구수',
                          pop_Seoul.columns[2] : '한국인',
                          pop_Seoul.columns[3] : '외국인',
                          pop_Seoul.columns[4] : '고령자'}, inplace=True)
pop_Seoul.head()

컬럼 이름에 문제가 있다면 rename 명령어를 통해 컬럼의 이름을 변경할 수 있습니다.

 

이렇게 여러 컬럼의 이름을 한 번에 변경도 가능합니다.

 

CCTV_Seoul.head()

pandas를 이용해서 CCTV와 인구현황 데이터를 파악할 수 있습니다.

 

우선 구별 CCTV 데이터를 조회합니다.

 

CCTV_Seoul.sort_values(by='소계', ascending=True).head(5)

구별 CCTV 데이터에서 전체 개수인 소계로 정렬을 했습니다.

 

정렬된 내용을 통해 CCTV의 전체 개수가 가장 작은 수는 도봉구라는 것을 알 수 있습니다.

 

CCTV_Seoul.sort_values(by='소계', ascending=False).head(5)

ascending를 False로 줘서 많은 순서대로 보여지도록 했습니다.

 

제일 많은 CCTV를 가지고 있는 구별은 강남구라는 것을 알 수 있습니다.

 

CCTV_Seoul['최근증가율'] = (CCTV_Seoul['2016년'] + CCTV_Seoul['2015년'] + \
                      CCTV_Seoul['2014년']) / CCTV_Seoul['2013년도 이전'] * 100
CCTV_Seoul.sort_values(by='최근증가율', ascending=False).head(5)

2014년부텅 2016년까지 최근 3년간 CCTV를 더하고 2013년 이전 CCTV 수로 나눠서 최근 3년간 CCTV 증가율을 계산했습니다.

 

최근 3년간 CCTV가 많이 증가한 구는 종로구인 것을 알 수 있습니다.

 

pop_Seoul.head()

pop_Seoul 변수를 확인해 봤는데 0번 행에 합계가 보입니다.

 

pop_Seoul.drop([0], inplace=True)
pop_Seoul.head()

서울시 전체 합계를 drop 명령어를 통해 지웠습니다.

 

pop_Seoul['구별'].unique()

구별 컬럼의 unique를 조사했습니다.

 

유니크 조사는 반복된 데이터는 하나로 나타나서 한 번이상 나타난 데이터를 확인해 줍니다.

 

pop_Seoul['외국인비율'] = pop_Seoul['외국인'] / pop_Seoul['인구수'] * 100
pop_Seoul['고령자비율'] = pop_Seoul['고령자'] / pop_Seoul['인구수'] * 100
pop_Seoul.head()

각 구별 전체 인구를 이용해서 구별 '외국인비율'과 '고령자비율'을 계산했습니다.

 

pop_Seoul.sort_values(by='인구수', ascending=False).head(5)

인구수로 정렬했습니다.

 

인구수가 제일 많은 구는 송파구인 것을 알 수 있습니다.

 

pop_Seoul.sort_values(by='외국인', ascending=False).head(5)

외국인 인구수도 위와 같은 방법으로 알아볼 수 있습니다.

 

외국인은 영등포구에 가장 많이 있습니다.

 

pop_Seoul.sort_values(by='외국인비율', ascending=False).head(5)

외국인 비율을 알아봤습니다.

 

외국인 숫자가 아닌 비율 또한 영등포구가 가장 높은 것을 알 수 있습니다.

 

pop_Seoul.sort_values(by='고령자', ascending=False).head(5)

고령자가 많은 곳은 송파구입니다.

 

pop_Seoul.sort_values(by='고령자비율', ascending=False).head(5)

고령자 숫자가 아닌 비율이 높은 곳은 강북구입니다.

 

data_result = pd.merge(CCTV_Seoul, pop_Seoul, on='구별')
data_result.head()

merge 명령으로 두 데이터의 공통된 컬럼인 '구별'로 merge할 수 있습니다.

 

del data_result['2013년도 이전']
del data_result['2014년']
del data_result['2015년']
del data_result['2016년']
data_result.head()

컬럼을 지우는 명령어입니다. 

 

행 방향으로 삭제하는 것은 drop이고 열을 삭제하는 명령어는 del입니다.

 

data_result.set_index('구별', inplace=True)
data_result.head()

그래프를 그릴 것을 생각하면 index는 구별로 하는 게 편합니다.

 

index를 설정하는 명령어가 set_index 명령어 입니다.

 

np.corrcoef(data_result['고령자비율'], data_result['소계'])

np.corrcoef(data_result['외국인비율'], data_result['소계'])

np.corrcoef(data_result['인구수'], data_result['소계'])

상관 계수를 계산하는 명령이 numpy에 있는 corrcoef 명령입니다.

 

이 명령의 결과는 행렬로 나타납니다.

 

CCTV 개수는 고령자비율, 외국인비율과는 관계가 없습니다.

 

data_result.sort_values(by='소계', ascending=False).head(5)

data_result.sort_values(by='인구수', ascending=False).head(5)

CCTV 개수와 인구수는 약한 상관계수로 조금 더 들여다 봅니다.

 

CCTV 현황 그래프로 분석하기

matplotlib이 기본적으로 가진 폰트는 한글을 지원하지 않습니다.

 

때문에 matplotlib의 폰트를 변경할 필요가 있습니다.

 

PC의 운영체제가 맥 OS나 윈도우 모두 배려합니다.

 

data_result.head()

CCTV 데이터와 인구 현황 데이터가 merge된 결과 변수 data_result를 확인합니다.

 

import platform

from matplotlib import font_manager, rc
plt.rcParams['axes.unicode_minus'] = False

if platform.system() =='Darwin':
    rc('font', family='AppleGothic')
elif platform.system() == 'Windows':
    path = "c:/Windows/Fonts/malgun.ttf"
    font_name = font_manager.FontProperties(fname=path).get_name()
    rc('font', family=font_name)
else:
    print('Unknown system ..  sorry ~ ~ ')

matplotlib이 기본적으로 가진 폰트는 한글을 지원하지 않기 때문에 matplotlib의 폰트를 변경할 필요가 없습니다.

 

plt.figure()
data_result['소계'].plot(kind='barh', grid=True, figsize=(10,10))
plt.show()

pandas 데이터 뒤에 plot 명령어를 붙여주면 바로 그려줍니다.

 

kind = 'barh'로 지정해서 수평바(bar)로 그리도록 합니다.

 

grid = True로 grid를 그리고 figsize로 그림 크기도 지정해 줍니다.

 

data_result['소계'].sort_values().plot(kind='barh', grid=True, figsize=(10,10))
plt.show()

위에 수평바 그래프를 정렬해서 봅니다.

 

한 눈에 볼 수 있어 좋습니다.

 

CCTV 개수는 강남구가 월등히 많은 것을 확인할 수 있습니다.

 

data_result['CCTV비율'] = data_result['소계'] / data_result['인구수'] * 100
data_result['CCTV비율'].sort_values().plot(kind='barh', grid=True, figsize=(10,10))
plt.show()

인구 대비 CCTV 비율을 계산해서 정렬합니다.

 

인구 대비 CCTV를 보면 종로와 용산이 많고 송파는 인구대비 CCTV가 적은 것을 볼 수 있습니다.

 

plt.figure(figsize=(6,6))
plt.scatter(data_result['인구수'], data_result['소계'], s = 50)
plt.xlabel('인구수')
plt.ylabel('CCTV')
plt.grid()
plt.show()

scatter 함수를 사용해 s = 50로 마커의 크기를 잡고 그립니다.

 

fp1 = np.polyfit(data_result['인구수'], data_result['소계'], 1)
fp1
f1 = np.poly1d(fp1)
fx = np.linspace(100000, 7000000, 100)

데이터를 대표하는 직선을 그립니다.

 

numpy의 polyfit 명령으로 직선을 만들어 줍니다.

 

이를 위해 x축과 y축의 데이터를 얻어야 하는데 x축 데이터는 numpy의 linespace로 만들고, y축은 poly1d로 만듭니다.

 

plt.figure(figsize=(10,10))
plt.scatter(data_result['인구수'], data_result['소계'], s=50)
plt.plot(fx, f1(fx), ls='dashed', lw=3, color='g')
plt.xlabel('인구수')
plt.ylabel('CCTV')
plt.grid()
plt.show()

직선이 데이터의 대표값 역할을 합니다.

 

인구수가 300,000일 때는 CCTV는 1,400 정도여야 합니다.

반응형

댓글