필요한 모듈 및 데이터 호출
import pandas as pd
CCTV_Seoul = pd.read_csv("../data/01. Seoul_CCTV.csv")
CCTV_Seoul.head()

CCTV_Seoul.columns

CCTV_Seoul.columns[0]

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

pop_Seoul = pd.read_excel("../data/01. Seoul_Population.xls")
pop_Seoul.head()

가져올 data의 필요한 부분의 index와 column 옵션주기
pop_Seoul = pd.read_excel("../data/01. Seoul_Population.xls", header=2, usecols="B, D, G, J, N")
pop_Seoul.head()

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()

CCTV_Seoul.head()

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

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

기존 컬럼이 없으면 추가, 있으면 수정
CCTV_Seoul["최근증가율"] = (
(CCTV_Seoul["2016년"] + CCTV_Seoul["2015년"] + CCTV_Seoul["2014년"]) / CCTV_Seoul["2013년도 이전"] * 100)
CCTV_Seoul.sort_values(by="최근증가율", ascending=False).head(5)

pop_Seoul.head()

0번재 index 제거
pop_Seoul.drop([0], axis=0, inplace=True)
pop_Seoul.head()

중복되지 않게 하나의 값들만 표시
pop_Seoul["구별"].unique()

중복되지 않은 값들의 총 계
len(pop_Seoul["구별"].unique())

외국인비율, 고령자비율 column 생성
pop_Seoul["외국인비율"] = pop_Seoul["외국인"] / pop_Seoul["인구수"] * 100
pop_Seoul["고령자비율"] = pop_Seoul["고령자"] / pop_Seoul["인구수"] * 100
pop_Seoul.head()

인구수 기준 내림차순 정렬
pop_Seoul.sort_values(["인구수"], ascending=False).head(5)

외국인 기준 내림차순 정렬
pop_Seoul.sort_values(["외국인"], ascending=False).head(5)

외국인비율 기준 내림차순 정렬
pop_Seoul.sort_values(["외국인비율"], ascending=False).head()

고령자 기준 내림차순 정렬
pop_Seoul.sort_values(by="고령자", ascending=False).head()

고령자비율 기준 내림차순 정렬
pop_Seoul.sort_values(by="고령자비율", ascending=False).head()

CCTV_Seoul.head(1)

pop_Seoul.head(1)

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

년도별 데이터 컬럼 삭제 (del, drop())
del data_result["2013년도 이전"]
del data_result["2014년"]
data_result.head(3)

data_result.drop(["2015년", "2016년"], axis=1, inplace=True)
data_result.head()

인덱스 변경 (set_index()) - 선택한 column을 dataframe의 index로 지정
data_result.set_index("구별", inplace=True)
data_result.head()

상관계수 (corr())
data_result.corr()

데이터의 기본적인 정보 확인
data_result.info()

새 column CCTV비율 추가
data_result["CCTV비율"] = (data_result["소계"] / data_result["인구수"]) * 100
data_result.head()

CCTV비율 기준 내림차순 정렬
data_result.sort_values(by="CCTV비율", ascending=False).head()

CCTV비율 기준 오름차순 정렬
data_result.sort_values(by="CCTV비율", ascending=True).head()

한글 깨짐 방지를 위한 setting (Windows용)
import matplotlib.pyplot as plt
%matplotlib inline
from matplotlib import rc
rc("font", family="Malgun Gothic")
data_result.head()

소계 column 시각화
data_result["소계"].plot(kind="barh", grid=True, figsize=(10, 10));

보기 좋게 다시 정렬
def drawGraph():
data_result["소계"].sort_values().plot(
kind="barh", grid=True, title="가장 CCTV가 많은 구", figsize=(10, 10));
drawGraph()

CCTV비율 column 시각화
def drawGraph():
data_result["CCTV비율"].sort_values().plot(
kind="barh", grid=True, title="가장 CCTV가 많은 구", figsize=(10, 10));
drawGraph()

데이터 확인
data_result.head()

인구수와 소계 column으로 scatter plot 그리기
def drawGraph():
plt.figure(figsize=(14, 10))
plt.scatter(data_result["인구수"], data_result["소계"], s=50)
plt.xlabel("인구수")
plt.ylabel("CCTV")
plt.grid(True)
plt.show()
drawGraph()

1차 직선 만들기 (경향선) with Numpy
import numpy as np
fp1 = np.polyfit(data_result["인구수"], data_result["소계"], 1)
fp1

f1 = np.poly1d(fp1)
f1

인구가 40만인 구에서 서울시의 전체 경향에 맞는 적당한 CCTV 수 계산
f1(400000)

경향선을 그리기 위한 X 데이터 생성
fx = np.linspace(100000, 700000, 100)
경향선 추가
def drawGraph():
plt.figure(figsize=(14, 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(True)
plt.show()
drawGraph()

그래프 다듬기
fp1 = np.polyfit(data_result["인구수"], data_result["소계"], 1)
f1 = np.poly1d(fp1)
fx = np.linspace(100000, 700000, 100)
기존 데이터 확인
data_result.head(3)

오차 데이터 추가
data_result["오차"] = data_result["소계"] - f1(data_result["인구수"])
data_result.head(1)

경향과 비교해서 오차가 많이 나는 데이터를 계산 (경향 대비 CCTV 많은 구 - 내림차순)
df_sort_f = data_result.sort_values(by="오차", ascending=False)
df_sort_f.head()

경향과 비교해서 오차가 많이 나는 데이터를 계산 (경향 대비 CCTV 적은 구 - 오름차순)
df_sort_t = data_result.sort_values(by="오차", ascending=True)
df_sort_t.head()

최종 그래프 생성 전 시각화 모듈 세부 설정
from matplotlib.colors import ListedColormap
# colormap 을 사용자 정의(user define)로 세팅
color_step = ["#e74c3c", "#2ecc71", "#95a9a6", "#2ecc71", "#3498db", "#3498db"]
my_cmap = ListedColormap(color_step)
정리된 데이터를 가지고 최종 시각화
def drawGraph():
plt.figure(figsize=(14, 10))
plt.scatter(data_result["인구수"], data_result["소계"], s=50, c=data_result["오차"], cmap=my_cmap)
plt.plot(fx, f1(fx), ls="dashed", lw=3, color="g")
for n in range(5):
# 상위 5개
plt.text(
df_sort_f["인구수"][n] * 1.02, # x 좌표
df_sort_f["소계"][n] * 0.98, # y 좌표
df_sort_f.index[n], # title
fontsize=15,
)
# 하위 5개
plt.text(
df_sort_t["인구수"][n] * 1.02,
df_sort_t["소계"][n] * 0.98,
df_sort_t.index[n],
fontsize=15
)
plt.xlabel("인구수")
plt.ylabel("CCTV")
plt.colorbar()
plt.grid(True)
plt.show()
drawGraph()

마무리는 항상 데이터 저장
data_result.to_csv("../data/01. CCTV_result.csv", sep=",", encoding="utf-8")