# -*- coding: utf-8 -*-
"""
Created on Thu Apr 23 09:49:21 2020
@author: admin
"""
'''
서울시 구별 CCTV 현황 분석하기
서울시 각 구별 CCTV 수를 파악하고,
인구대비 CCTV 비율을 파악해서 순위 비교
인구대비 CCTV의 평균치를 확인하고
그로부터 CCTV가 과하게 부족한 구를 확인
Python 기본 문법 / Pandas 와 Matplotlib의 기본적 사용법을 이용한 시각화
단순한 그래프 표현에서
한 단계 더 나아가 경향을 확인하고 시각화하는 기초 확인
'''
import pandas as pd
import numpy as np
# CCTV 데이터와 인구 데이터 합치고 분석하기
##CCTV 데이터 읽기
CCTV_Seoul = pd.read_csv('./data/01. CCTV_in_Seoul.csv', encoding='UTF-8')
#데이터프레임
CCTV_Seoul.head()
CCTV_Seoul.columns
CCTV_Seoul.columns[0]
#칼럼명 변경 : 기관명을 구별로 변경
CCTV_Seoul.rename(columns={CCTV_Seoul.columns[0]:'구별'}, inplace=True)
CCTV_Seoul.head()
# 인구데이터 읽기 1
pop_Seoul = pd.read_excel('./data/01. population_in_Seoul.xls', encoding='UTF-8')
pop_Seoul.head()
#인구 데이터 읽기2 - 필요한 데이터만 선별하여 읽기
pop_Seoul = pd.read_excel('./data/01. population_in_Seoul.xls',
header=2, # 헤더 두 줄 건너 뛰고 나타내라
usecols='B, D, G, J, N', # 사용할 컬럼 지정
encoding='utf-8')
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 데이터 파악하기
# 소계 순으로 정렬(오름차순)
CCTV_Seoul.sort_values(by='소계', ascending=True).head(5)
# 소계 순으로 정렬(내차순)
CCTV_Seoul.sort_values(by='소계', ascending=False).head(5)
#sort_values : 원본에 정렬순으로 저장되는 것은 아니다.
# 최근증가율 = (2016년+2015년+2014년)/2013년도 이전 * 100
CCTV_Seoul['최근증가율']=(CCTV_Seoul['2016년']+CCTV_Seoul['2015년']+ \
CCTV_Seoul['2014년']) / CCTV_Seoul['2013년도 이전'] * 100
CCTV_Seoul.sort_values(by='최근증가율', ascending=False).head()
#서울시 인구데이터 파악하기
pop_Seoul.head()
#첫번째 합계 행 삭제
pop_Seoul.drop([0],inplace=True)
pop_Seoul,head()
#'구별' 칼럼의 중복값 제거
pop_Seoul['구별'].unique()
#'구별' 칼럼의 NULL 값 확인
#isnull() : 널값의 행값과 널값을 인덱스 번호를 반환 시켜준다.
# 구별 인구수 한국인 외국인 고령자
#26 NaN NaN NaN NaN NaN
pop_Seoul[pop_Seoul['구별'].isnull()]
# '구별' 컬럼의 NULL값 있는 행 제거
pop_Seoul.drop([26],inplace=True)
pop_Seoul.head()
'''
데이터 분석
1.분석데이터 수집(R or python )
2.수집된 데이터 형식 확인 및 로컬 전처리
3.분석 prg에서 수집 데이터 읽기
4.읽은 데이터 확인 및 3차 전처리
'''
#외국인비율과 고령자 비율 추가
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()
pop_Seoul.sort_values(by='외국인', ascending=False).head()
pop_Seoul.sort_values(by='외국인비율', ascending=False).head()
pop_Seoul.sort_values(by='고령자', ascending=False).head()
pop_Seoul.sort_values(by='고령자비율', ascending=False).head()
# 시각화 작업을 위함 구이름('구별')을 index화
data_result.set_index('구별', inplace=True)
data_result.head()
###CCTV 데이터와 인구 데이터 합치고 분석하기
# 두개의 데이터프레임을 합할 경우 동일 컬럼명은 하나('구별')로 통일 된다.
data_result = pd.merge(CCTV_Seoul,pop_Seoul, on='구별')
data_result.head()
# CCTV에 대한 '소계' 컬럼을 제외한 나머지 CCTV 데이터 삭제
del data_result['2013년도 이전']
del data_result['2014년']
del data_result['2015년']
del data_result['2016년']
data_result.head()
#CCTV와 각 칼럼에 대한 상솬관계 분석
# 상관관계 함수 :np.corrcoef()
np.corrcoef(data_result['고령자비율'],data_result['소계'])
np.corrcoef(data_result['외국인비율'],data_result['소계'])
np.corrcoef(data_result['인구수'],data_result['소계'])
data_result.sort_values(by='소계', ascending=False).head(5)
#csv로 저장시켜주는 함수
data_result.to_csv('data_result.csv')
# 데이터 읽히는지 확인하기
pd.read_csv('data_result.csv', encoding='utf-8')
# CCTV와 인구현황 그래프로 분석하기
import platform
import pandas as pd
import numpy as np
# 폰트 설정(특히 한글부분)
import matplotlib.pyplot as plt
from matplotlib import font_manager, rc
plt.rcParams['axes.unicode_minus']=False
data_result = pd.read_csv('data_result.csv', encoding='utf-8')
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')
# CCTV 비율을 구하고 그에 따른 시각화 작업
data_result['CCTV비율'] = data_result['소계'] / data_result['인구수'] * 100
data_result['CCTV비율'].sort_values().plot(kind='barh', grid=True, figsize=(10,10))
plt.show()
# 산점도(인구수와 소계)
plt.figure(figsize=(6,6))
plt.scatter(data_result['인구수'], data_result['소계'], s=50)
plt.xlabel('인구수')
plt.ylabel('CCTV')
plt.grid()
plt.show()
# 인구수와 CCTV는 상관계수가 양의 값이므로 산점도와 직선
# 직선 구하기 (Polyfit을 이용한 회귀선)
# polyfit 함수를 이용해서 예측 모델 z의 계수를 생성
fp1 = np.polyfit(data_result['인구수'], data_result['소계'],1)
fp1
# 만들어진 예측 모델을 이용한 그래프 그리기
f1 = np.poly1d(fp1) # y축 데이터
fx = np.linspace(100000, 700000, 100) # x축 데이터
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()
'''인구수가 310000 정도일 때, cctv는 1100대가 적당하다'''
# 조금더 설득력 있는 자료 만들기
'''
직선이 전체 데이터의 대표값 역할을 한다면
인구수가 300,000일경우 CCTV는 1100정도여야 한다는 결론
가독성 향상을 위해 오차를 계산할 수 있는 코드 작성후,
오차가 큰 순으로 데이터를 정렬
'''
fp1 = np.polyfit(data_result['인구수'], data_result['소계'],1)
f1 = np.poly1d(fp1) # y축 데이터
fx = np.linspace(100000, 700000, 100) # x축 데이터
data_result['오차'] = np.abs(data_result['소계']- f1(data_result['인구수']))
df_sort = data_result.sort_values(by = '오차', ascending =False)
df_sort.head()
#plot 크기 설정
plt.figure(figsize=(14,10))
#산점도
plt.scatter(data_result['인구수'],data_result['소계'],
c =data_result['오차'], s=50)
#회귀선
plt.plot(fx,f1(fx),ls='dashed', lw=3, color='g')
#주요 10개 지역 구이름 출력
for n in range(10):
plt.text(df_sort['인구수'][n]*1.02, df_sort['소계'][n]*0.98,
df_sort.index[n], fontsize=15)
plt.xlabel('인구수')
plt.ylabel('인구당비율')
plt.colorbar() #오른쪽에 생상바
plt.grid() #가이드라인
plt.show()
# =============================================================================
# 강남 3구는 안전한가 ?
# =============================================================================
'''
강남 3구의 주민들이 자신들이 거주하는 구의 체감 안전도를
높게 생각한다는 기사를 확인해보도록 한다.
기사 원문 :
Matplotlib 의 heatmap 등을 그릴 때
cmap의 디폴트 설정이 변경되어 heatmap 등에서 cmap을 적용할 때
옵션을 잡아주어야 동일한 효과가 나타난다.
Folium 0.4.0으로 버전업 되면서
choropleth 명령에서 geo_str 옵션명이 geo_data 옵션명으로 변경됨.
circle marker 적용할 때, fill=True 옵션을 반드시 사용해야 함.
'''
##########
# 데이터 정리하기
# 필요한 모듈을 import
import numpy as np
import pandas as pd
'''다운받은 데이터(csv) 파일을 읽는다,
콤마(,)로 천단위가 구분되어 있고, 한글 인코딩은 euc-kr
'''
crime_anal_police = pd.read_csv('./data/02. crime_in_Seoul.csv',
thousands = ',', encoding='euc-kr')
r=crime_anal_police.head()
print(r)
'''
관서별로 되어 있는 데이터를 소속 구별로 변경
1. 경찰서 이름으로 구 정보 얻기
'''
# 구글 맵스를 사용해서 경찰서의 위치(위도, 경도) 정보를 받아온다.
import googlemaps
# 자신의 key를 사용.
gmaps_key = "AIzaSyC8BVOCtGMXacY8URBfmH1SWiYIErRWJ5M"
gmaps = googlemaps.Client(key=gmaps_key)
r=gmaps.geocode('서울중부경찰서', language='ko')
print(r)
#중부서, 수서서 => 서울**경찰서로 변경
station_name=[]
for name in crime_anal_police['관서명']:
station_name.append('서울'+ str(name[:-1])+'경찰서')
print(station_name)
# 경찰서 이름을 이용하여 주소 얻기
station_address = []
station_lat =[]
station_lng =[]
for name in station_name:
tmp = gmaps.geocode(name, language='ko')
station_address.append(tmp[0].get("formatted_address"))
tmp_loc = tmp[0].get("geometry")
station_lat.append(tmp_loc['location']['lat'])
station_lng.append(tmp_loc['location']['lng'])
print(name+'-->' + tmp[0].get("formatted_address"))
print(station_address)
station_address
for name in station_name:
tmp=gmaps.geocode(name,language='ko')
'''
[{'address_components':
[{'long_name': '617',
'short_name': '617',
'types': ['premise']},
{'long_name': '개포로',
'short_name': '개포로',
'types': ['political', 'sublocality', 'sublocality_level_4']},
{'long_name': '개포동', 'short_name': '개포동',
'types': ['political', 'sublocality', 'sublocality_level_2']},
{'long_name': '강남구', 'short_name': '강남구',
'types': ['political', 'sublocality', 'sublocality_level_1']},
{'long_name': '서울특별시', 'short_name': '서울특별시',
'types': ['administrative_area_level_1', 'political']},
{'long_name': '대한민국', 'short_name': 'KR',
'types': ['country', 'political']},
{'long_name': '135-240', 'short_name': '135-240',
'types': ['postal_code']}],
'formatted_address': '대한민국 서울특별시 강남구 개포동 개포로 617',
'geometry':
{'location': {'lat': 37.49349, 'lng': 127.0772119}, 'location_type': 'ROOFTOP',
'viewport':
{'northeast': {'lat': 37.4948389802915, 'lng': 127.0785608802915},
'southwest': {'lat': 37.49214101970851, 'lng': 127.0758629197085}}},
'place_id': 'ChIJY2ee_TGkfDURAWUtC8jBHag',
'plus_code':
{'compound_code': 'F3VG+9V 대한민국 서울특별시',
'global_code': '8Q99F3VG+9V'},
'types': ['establishment', 'point_of_interest', 'police']
}]
'''
station_address.append(tmp[0].get("formatted_address"))
#formatted_address': '대한민국 서울특별시 강남구 개포동 개포로 617'
tmp_loc=tmp[0].get("geometry")
#{'location': {'lat': 37.49349, 'lng': 127.0772119}
#print(tmp_loc)
'''
{'location': {'lat': 37.49349, 'lng': 127.0772119},
'location_type': 'ROOFTOP',
'viewport': {'northeast': {'lat': 37.4948389802915, 'lng': 127.0785608802915},
'southwest': {'lat': 37.49214101970851, 'lng': 127.0758629197085}}}
'''
station_lat.append(tmp_loc['location']['lat'])
station_lng.append(tmp_loc['location']['lng'])
print(name+'-->' + tmp[0].get("formatted_address"))
'''
서울중부경찰서-->대한민국 서울특별시 중구 을지로동 수표로 27
서울종로경찰서-->대한민국 서울특별시 종로구 종로1.2.3.4가동 율곡로 46
서울남대문경찰서-->대한민국 서울특별시 중구 회현동 한강대로 410
서울서대문경찰서-->대한민국 서울특별시 서대문구 충현동 통일로 113 ....
'''
print(station_address)
print(station_lng)
'''
금천 경찰서의 경우 관악구로 되어 있어서 금천구로 변경
'''
crime_anal_police[crime_anal_police['관서명']=='금천서']
crime_anal_police.loc[crime_anal_police['관서명']==금천서,
['구별']] =='금천구'
crime_anal_police[crime_anal_police['관서명']=='금천서']
#현재까지 작업 내용 저장.
crime_anal_police.to_csv('./dada/02_crime_in_Seoul_include_gu_name.csv',
sep = ',', encoding='utf-8')
####### 범죄데이터 구별로 정리하기
from GangnamSatety_20200423 import station_lng, station_lat
crime_anal_raw = pd.read_csv('./data/02_crime_in_Seoul_include_gu_name.csv', encoding='utf-8')
crime_anal_raw.head()
### pandas의 pivot_table
'''
pd.pivot_table(df, 피벗 테이블을 만들기 위한 기본 데이터
index = [], pivot_table의 index를 설정(multi index도 가능)
columns = [], 원하는 columns을 설정
values = [], columns에 해당하는 값
aggfunc = [], 분석을 위한 파라미터
예) np.sum, np.mean 사용
fill_value = 0, Nan 값을 채우기.
margins = True) 모든 데이터의 결과를 아래에 붙일 것인지 설정
--> 원하는 컬럼을 인덱스화 시켜서 나머지 데이터들을 재정렬시켜주는 것이 피벗 테이블의 역할이다.
'''
# pivot_table을 이용
# 저장한 데이터를 관서별에서 구별로..
crime_anal = pd.pivot_table(crime_anal_raw, index='구별', aggfunc=np.sum)
crime_anal.head()
print(crime_anal)
print(type(crime_anal))
'''
각 범죄별 검거율을 계산하고,
검거 건수는 검거율로 대체한 후, 검거 건수는 삭제
'''
crime_anal['강간검거율'] = crime_anal['강간 검거']/crime_anal['강간 발생']*100
crime_anal['강도검거율'] = crime_anal['강도 검거']/crime_anal['강도 발생']*100
crime_anal['살인검거율'] = crime_anal['살인 검거']/crime_anal['살인 발생']*100
crime_anal['절도검거율'] = crime_anal['절도 검거']/crime_anal['절도 발생']*100
crime_anal['폭력검거율'] = crime_anal['폭력 검거']/crime_anal['폭력 발생']*100
del crime_anal['강간 검거']
del crime_anal['강도 검거']
del crime_anal['살인 검거']
del crime_anal['절도 검거']
del crime_anal['폭력 검거']
print(crime_anal.head())
'''
100이 넘는 숫자들은 100으로 처리
'''
con_list = ['강간검거율', '강도검거율', '살인검거율', '절도검거율', '폭력검거율']
for columns in con_list:
crime_anal.loc[crime_anal[column]>100, column] =100
print(crime_anal.head())
# 컬럼 뒤에 발생이라는 단어 삭제 : rename()을 이용
crime_anal.rename(columns = {'강간 발생':'강간',
'강도 발생':'강도',
'살인 발생':'살인',
'절도 발생':'절도',
'폭력 발생':'폭력',}, inplace = True)
print(crime_anal.head())
################
# 데이터 표현을 위해 전처리
'''
강도와 살인은 두 자리수,
절도와 폭력은 네 자리수로 구성 되어 있어
각각을 비슷한 범위에 놓고 비교하는 것이 편리하기 때문에
각 컬럼별로 정규화(normalize) 작업
각 항목의 최대값을 1로 두면,
추후 범죄발생 건수를 종합적으로 비교할 때 편리
각각, 강도, 살인, 절도, 폭력에 대하여
각 컬럼별로 정규화(normalize)
'''
'''
파이썬의 머신러닝에 관한 모듈 중
scikit learn에 있는 전처리(preprocessing) 도구에는
최소, 최대값을 이용하여 정규화시키는 함수가 존재 : MinMaxScaler()
'''
from sklearn import preprocessing
col =['강간', '강도', '살인', '절도', '폭력']
x = crime_anal[col].values
min_max_scaler = preprocessing.MinMaxScaler()
x_scaled = min_max_scaler.fit_transform(x.astype(float))
crime_anal_norm = pd.DataFrame(x_scaled, columns = col, index = crime_anal.index)
# 정규화된 데이터프레임에 검거율 추가
col2 = ['강간검거율', '강도검거율', '살인검거율', '절도검거율', '폭력검거율']
crime_anal_norm[col2] = crime_anal[col2]
print(crime_anal_norm.head())
# CCTV_result.csv 에서 구별 인구수와 CCTV 개수만 추가
result_CCTV = pd.read_csv('./data/01. CCTV_result.csv', encoding='UTF-8', index_col = '구별')
crime_anal_norm[['인구수', 'CCTV']] = result_CCTV[['인구수', '소계']]
print("인구수와 CCTV 개수 =>", crime_anal_norm.head())
# 발생 건수의 합을 '범죄'라는 컬럼으로 합하여 추가
col = ['강간', '강도', '살인', '절도', '폭력']
crime_anal_norm['범죄'] = np.sum(crime_anal_norm[col], axis=1)
print("범죄라는 컬럼으로 합 =>", crime_anal_norm.head())
# 검거율도 통합하여 추가
col = ['강간검거율','강도검거율', '살인검거율','절도검거율','폭력검거율']
crime_anal_norm['검거'] = np.sum(crime_anal_norm[col], axis=1)
print('검거율도 통합 =>', crime_anal_norm.head())
import matplotlib.pyplot as plt
import seaborn as sns # 다수의 상관관계 표현하기 위한 모듈
import platform # 한글 폰트 설정하기 위한 모듈
import pivotTable_20200423
from pivotTable_20200423 import crime_anal_norm
# 한글 폰트 설정
path = "c:/Windows/Fonts/malgun.ttf"
from matplotlib import font_manager, rc
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')
# pairplot() 상관관계 : '강도', '살인', '폭력'
#'''
sns.pairplot(crime_anal_norm, vars=["강도", "살인", "폭력"], kind = 'reg', size=3)
plt.show()
#'''
# pairplot() 상관관계 : "인구수", "CCTV", "살인", "강도"
# '''
sns.pairplot(crime_anal_norm, x_vars=["인구수", "CCTV"], y_vars =["살인","강도"], kind='reg', size=3)
plt.show()
# '''
# pairplot() 상관관계 : "인구수", "CCTV", "살인검거율", "폭력검거율"
sns.pairplot(crime_anal_norm, x_vars=["인구수", "CCTV"], y_vars=["살인검거율", "폭력검거율"], kind='reg', size=3)
plt.show()
'''
살인 및 폭력 검거율과 CCTV의 관계가 음의 상관계수도 보여줌.
인구수와 살인 및 폭력 검거율도 음의 상관관계를 보임.
'''
# pairplot() 상관관계 : "인구수", "CCTV", "절도검거율", "강도검거율"
sns.pairplot(crime_anal_norm, x_vars=["인구수", "CCTV"], y_vars=["절도검거율","강도검거율"],kind = 'reg', size=3)
plt.show()
# 검거율의 합계인 검거 항목 최고 값을 100으로 한정한 후, 그 값으로 정렬
tmp_max = crime_anal_norm['검거'].max()
crime_anal_norm['검거'] = crime_anal_norm['검거'] / tmp_max *100
crime_anal_norm_sort = crime_anal_norm.sort_values(by='검거', ascending=False)
crime_anal_norm_sort.head()
# heatmap 으로 시각화
target_col = ['강간검거율','강도검거율','살인검거율','절도검거율','폭력검거율']
crime_anal_norm_sort = crime_anal_norm.sort_values(by = '검거', ascending=False)
plt.figure(figsize=(10,10))
sns.heatmap(crime_anal_norm_sort[target_col],
annot=True, fmt='f',
linewidths=.5, #linewidth는 칸 간격 의미.
cmap = 'RdPu')
plt.title('범죄 검거 비율 (정규화된 검거의 합으로 정렬)')
plt.show()
# 발생 건수 정렬하여 heatmap으로 시각화
target_col = ['강간', '강도', '살인' ,'절도', '폭력', '범죄']
crime_anal_norm['범죄'] = crime_anal_norm['범죄'] / 5
crime_anal_norm_sort = crime_anal_norm.sort_values(by ='범죄', ascending=False)
plt.figure(figsize=(10,10))
sns.heatmap(crime_anal_norm_sort[target_col],
annot=True, fmt='f',
linewidths=.5,
cmap='RdPu')
plt.title("범죄비율 (정규화 된 발생 건수로 정렬)")
plt.show()
import json
geo_path = './data/02. skorea_municipalities_geo_simple.json'
geo_str = json.load(open(geo_path, encoding='utf-8'))
crime_anal_raw['lat'] = station_lat
crime_anal_raw['lng'] = station_lng
col = ['살인 검거', '강도 검거', '강간 검거', '절도 검거', '폭력 검거']
tmp = crime_anal_raw[col] / crime_anal_raw[col].max()
crime_anal_raw['검거'] = np.sum(tmp, axis=1)
crime_anal_raw.head()
import folium
import webbrowser
################
# 지도를 이용한 시각화 작업을 위해 지도의 중심 좌표를 이용하여 12배 확대
map = folium.Map(location = [37.5502, 126.982], zoom_start=12)
# 로드된 지도 위에 각 경찰서의 검거율을 x10 배수의 크기(반지름)로 원을 그려준다.(외경 선과 내면 색 지정)
# .add_to()함수로 불러온 map 에 더해줌
for n in crime_anal_raw.index:
folium.CircleMarker([crime_anal_raw['lat'][n], crime_anal_raw['lng'][n]],
radius = crime_anal_raw['검거'][n]*10,
color = '#3186cc',
fill_color = '#3186cc',
fill=True).add_to(map)
# map html파일로 저장 후 열기
map
map.save('folium_kr2.html')
webbrowser.open_new("folium_kr2.html")
##############
map = folium.Map(location = [37.5502, 126.982], zoom_start=12)
map.choropleth(geo_data=geo_str,
data = crime_anal_norm['범죄'],
columns = [crime_anal_norm.index, crime_anal_norm['범죄']],
fill_color='PuRd', #PuRd, YlGnBu
key_on = 'feature.id')
for n in crime_anal_raw.index:
folium.CircleMarker([crime_anal_raw['lat'][n], crime_anal_raw['lng'][n]],
radius = crime_anal_raw['검거'][n]*10,
color = '#3186cc',
fill_color = '#3186cc',
fill=True).add_to(map)
map.save('folium_kr3.html')
webbrowser.open_new("folium_kr3.html")
# =============================================================================
# 위에는 TL_SCCO_SIG_WGS84.json, Total_People_2018.csv 데이터로 맵 구역별로 나눈거 하기
# 아래는 외국인 거주자 인구수 데이터
# =============================================================================
import matplotlib.pyplot as plt
import seaborn as sns # 다수의 상관관계 표현하기 위한 모듈
import platform # 한글 폰트 설정하기 위한 모듈
import pandas as pd
import numpy as np
import json
import folium
import webbrowser
pop_Seoul = pd.read_excel('./data/01. population_in_Seoul.xls', encoding='utf-8')
pop_Seoul.head()
pop_Seoul = pd.read_excel('./data/01. population_in_Seoul.xls',
header=2, # 2줄 건너뛰고 읽어온다
usecols='B, D, J', # 원하는 셀만 골라서 가져오기
encoding='utf-8')
pop_Seoul.head()
# 알기 쉬운 컬럼명으로 변경
pop_Seoul.rename(columns={pop_Seoul.columns[0]:'구별',
pop_Seoul.columns[1]:'인구수',
pop_Seoul.columns[2]:'외국인거주인구'}, inplace=True)
pop_Seoul.head()
pop_Seoul.drop([0], inplace=True)
pop_Seoul.head()
# '구별' 컬럼의 중복값제거
pop_Seoul['구별'].unique()
# '구별' 컬럼의 NULL 값 확인
pop_Seoul[pop_Seoul['구별'].isnull()] # NULL 값이 있는 행 번호 & 값들을 함께 반환시켜준다.
# '구별' 컬럼의 NULL값 있는 행 제거
pop_Seoul.drop([26],inplace=True)
pop_Seoul.head()
#비율 추가
pop_Seoul['외국인비율']=pop_Seoul['외국인거주인구']/pop_Seoul['인구수']*100
#각 컬럼 확인
pop_Seoul.sort_values(by='인구수', ascending=False).head()
pop_Seoul.sort_values(by='외국인거주인구', ascending=False).head()
# 시각화 작업을 위한 구 이름('구별')을 index 화
pop_Seoul.set_index('구별', inplace=True)
pop_Seoul
geo_path = './data/02. skorea_municipalities_geo_simple.json'
geo_str = json.load(open(geo_path, encoding='utf-8'))
# # 지도를 이용한 시각화 작업을 위해 지도의 중심 좌표를 이용하여 12배 확대
map = folium.Map(location = [37.5502, 126.982], zoom_start=12)
map.choropleth(geo_data=geo_str,
data = pop_Seoul['외국인비율'],
columns = [pop_Seoul.index, pop_Seoul['외국인비율']],
fill_color='PuRd',
key_on = 'feature.id')
map.save('folium_foreingn.html')
webbrowser.open_new("folium_foreingn.html")
':: IT > python' 카테고리의 다른 글
Flask 입문, 파이썬과 HTML, 폼으로 데이터 전송받기 (0) | 2020.05.06 |
---|---|
[파이썬] 데이터 전처리 20200424 (0) | 2020.04.27 |
[파이썬]수집된 데이터 형식 확인 및 로컬 전처리 (0) | 2020.04.23 |
[파이썬] 분석데이터 수집 및 분석(전처리) (0) | 2020.04.23 |
[python] Pandas 를 사용한 데이터 분석 기초, 크롤링 (0) | 2020.04.21 |