해당 글은 제로베이스데이터스쿨 학습자료를 참고하여 작성되었습니다
서울시 범죄율 분석
- 과거에 서울 강남3구의 체감안전도가 높다는 기사가 있었는데 당시에 정말로 안전했는지 지도시각화를 통해 분석해보자
데이터출처 : 공공데이터포털
제로베이스에서 수정한 2016년도 데이터 활용
- 서울시 범죄 현황 데이터 확보
- 서울시 범죄 현황 데이터 정리
- google maps를 이용한 데이터 정리
- 구별데이터로 변경하기
- 범죄데이터 정렬을 위한 데이터 정리
- 범죄 현황 데이터 시각화
- 서울시 범죄 현황 지도 시각화
- 서울시 범죄 현황 발생 장소 분석
📝입력
import numpy as np import pandas as pd crime_raw_data = pd.read_csv( '../data/02. crime_in_Seoul.csv', encoding='euc-kr', thousands=",") # 데이터 확인 crime_raw_data.info() # 데이터에 Nan값이 많음을 확인 -> 의미있는 값만 사용하기로 판단 crime_raw_data = crime_raw_data[crime_raw_data['죄종'].notnull()] crime_raw_data
🧾출력
🧾crime_raw_data.info()
🧾crime_raw_data
📝입력
crime_station = crime_raw_data.pivot_table( crime_raw_data, index=['구분'], columns=['죄종', '발생검거'], aggfunc=[np.sum] # 데이터확인 crime_station.head() # pivot_table의 구조를 수정하기로 결정 crime_station.columns = crime_station.columns.droplevel([0, 1]) crime_station.head() )
🧾출력
🧾수정 전 crime_station.head()
🧾수정 후 crime_station.head()
구글 클라우드 플랫폼으로 접속결제로 이동계정만들기 클릭
이후 절차에 따라서 계정을 생성한다
계정 생성 후 계정관리로 이동
아래의 그림을 따라 이동한다
프로젝트를 생성한다
검색창에서 geocoding을 검색해서 들어간 후 사용으로 설정
구글 맵스 플랫폼으로 이동 후 API 제한사항, geocoding API를 선택하고 키 제한 클릭
사용자인증정보로 들어가서 키를 복사해서 Python에 활용한다
오류발생
- '관악'에서 주소지가 정상적으로 출력되지 않음
해결
- 확인 결과, '관악'에서만 오류가 발생하였으므로 사용자가 직접처리
📝입력
import googlemaps gmaps_key = 'Your_Google_API_Key' gmaps = googlemaps.Client(key=gmaps_key) # 데이터 구조 확인, 데이터추출방법 결정 gmaps.geocode("서울영등포경찰서", language='ko') # # 데이터프레임에 구조만들기 crime_station['구별'] = np.nan crime_station['lat'] = np.nan crime_station['lng'] = np.nan # # 주소, 위도, 경도 정보 가져오기 count = 0 for idx, rows in crime_station.iterrows(): # 서울XX경찰서를 구글맵스에 검색해서 데이터를 가져옴 station_name = '서울시 ' + str(idx) + '경찰서' tmp = gmaps.geocode(station_name, language='ko') # # 가져온 데이터 중 주소와 위도,경도를 변수에 저장 tmp_gu = tmp[0].get('formatted_address') lat = tmp[0].get('geometry')['location']['lat'] lng = tmp[0].get('geometry')['location']['lng'] # # 변수에 있는 데이터를 데이터프레임에 저장 crime_station.loc[idx, 'lat'] = lat crime_station.loc[idx, 'lng'] = lng # # '관악' 오류 해결 try: crime_station.loc[idx, '구별'] = tmp_gu.split()[2] except: if idx == '관악': crime_station.loc['관악', '구별'] = '관악구' else: crime_station.loc[idx, '구별'] = np.nan # count += 1 # 데이터프레임의 머리 구조를 1줄로 간략화 tmp = [ crime_station.columns.get_level_values(0)[n] + crime_station.columns.get_level_values(1)[n] for n in range(len(crime_station.columns.get_level_values(0))) ] crime_station.columns = tmp crime_station.head() # 데이터 저장 crime_station.to_csv("../data/02. crime_in_Seoul_raw.csv", sep=",", encoding='utf-8')
🧾출력
🧾crime_station.head()
📝입력
import pandas as pd
import numpy as np
crime_anal_station = pd.read_csv("../data/02. crime_in_Seoul_raw.csv", index_col=0, encoding='utf-8')
# 구별로 데이터 정리
crime_anal_gu = pd.pivot_table(crime_anal_station, index='구별', aggfunc=np.sum)
del crime_anal_gu['lat']
del crime_anal_gu['lng']
# 각 범죄의 검거율 생성
target = ['강간검거율', '강도검거율', '살인검거율', '절도검거율','폭력검거율']
num = ['강간검거', '강도검거', '살인검거','절도검거','폭력검거']
den = ['강간발생', '강도발생', '살인발생', '절도발생', '폭력발생']
crime_anal_gu[target] = crime_anal_gu[num].div(crime_anal_gu[den].values) * 100
# 불필요한 5대 범죄 검거 컬럼 제거
del crime_anal_gu['강간검거']
del crime_anal_gu['강도검거']
crime_anal_gu.drop(['살인검거', '절도검거', '폭력검거'], axis=1, inplace=True)
# 검거율 100으로 제한, 컬럼명 변경
crime_anal_gu[crime_anal_gu[target]>100] = 100
crime_anal_gu.rename(
columns={
'강간발생': '강간',
'강도발생': '강도',
'살인발생': '살인',
'절도발생': '절도',
'폭력발생': '폭력',
}, inplace=True
)
crime_anal_gu.head()
🧾출력 : crime_anal_gu.head()
📝입력
# 데이터 정규화 : 최소값은 0, 최고값은 1
col = ['살인', '강도', '강간', '절도', '폭력']
crime_anal_norm = crime_anal_gu[col] / crime_anal_gu[col].max()
# 검거율 추가
col2 = ['강간검거율', '강도검거율', '살인검거율', '절도검거율', '폭력검거율']
crime_anal_norm[col2] = crime_anal_gu[col2]
# CCTV 데이터 추가
result_CCTV = pd.read_csv(
"../data/01. CCTV_result.csv", encoding='utf-8', index_col='구별'
)
crime_anal_norm[['인구수', 'CCTV']] = result_CCTV[['인구수', '소계']]
# 범죄와 검거 컬럼 추가
col = ['살인', '강도', '강간', '절도', '폭력']
col2 = ['강간검거율', '강도검거율', '살인검거율', '절도검거율', '폭력검거율']
crime_anal_norm['범죄'] = np.mean(crime_anal_norm[col], axis=1)
crime_anal_norm['검거'] = np.mean(crime_anal_norm[col2], axis=1)
crime_anal_norm.head()
🧾출력 : crime_anal_norm.head()
- matplotlib을 기반으로 다양한 색상 테마와 통계용 차트 등의 기능을 추가한 시각화패키지
예제데이터셋 : tips
예제데이터셋 : flights
예제데이터셋 : iris
예제데이터셋 : anscombe
오류발견
데이터수집 코드 수정
# 주소, 위도, 경도 정보 가져오기
count = 0
for idx, rows in crime_station.iterrows():
# 서울XX경찰서를 구글맵스에 검색해서 데이터를 가져옴
station_name = '서울시 ' + str(idx) + '경찰서'
tmp = gmaps.geocode(station_name, language='ko')
# 가져온 데이터 중 주소와 위도,경도를 변수에 저장
tmp_gu = tmp[0].get('formatted_address')
lat = tmp[0].get('geometry')['location']['lat']
lng = tmp[0].get('geometry')['location']['lng']
print(tmp_gu)
# 변수에 있는 데이터를 데이터프레임에 저장
crime_station.loc[idx, 'lat'] = lat
crime_station.loc[idx, 'lng'] = lng
# '강서', '관악' 오류 해결
if idx in ['관악', '강서']:
if idx == '관악':
crime_station.loc['관악', '구별'] = '관악구'
elif idx == '강서':
crime_station.loc['강서', '구별'] = '강서구'
else:
crime_station.loc[idx, '구별'] = tmp_gu.split()[2]
print(count)
count += 1