관리 메뉴

log.Sehee

[데이터 취업 스쿨 스터디 노트] Google Maps API / Seaborn / 서울시 범죄 검거 현황 2 - 3 본문

Zerobase DS School

[데이터 취업 스쿨 스터디 노트] Google Maps API / Seaborn / 서울시 범죄 검거 현황 2 - 3

Sehe_e 2024. 8. 1. 20:25

 


 

Google Maps API

 

구글맵 conda 설치

conda install -c conda-forge googlemaps

 

Google Cloud에서 Google Map API Key 받기.

프로젝트 생성 후 'geocoding API' 설치. API 제한 설정 후 사용

 

import googlemaps

gmaps_key = 발급받은 키 입력
gmaps = googlemaps.Client(key=gmaps_key)

 

출력 데이터 확인

gmaps.geocode('서울영등포경찰서', language='ko')

 

정보 얻기

# 장소 정보 get
tmp[0].get('geometry')['location']

 

# 위도 경도 get
print(tmp[0].get('geometry')['location']['lat'])
print(tmp[0].get('geometry')['location']['lng'])

 

# 지역구 정보 get
tmp[0].get('formatted_address').split()    # ['대한민국', '서울특별시', '영등포구', '국회대로', '608']
tmp[0].get('formatted_address').split()[2]

 

구별, 위도, 경도 column 추가

crime_station['구별'] = np.nan
crime_station['lat'] = np.nan
crime_station['lng'] = np.nan

crime_station.head()

 

 


 

+ 강의에서는 강간 / 강간, 추행 column이 각각 존재하는데 내 화면에서는 강간이 Null 값인 index는 강간, 추행 데이터가 존재하고 강간,추행 column이 Null 값인 index는 강간 데이터가 존재한다. 그러므로 강간 / 강간, 추행 column을 합치기로 결정.

 

fill_value 옵션 추가하여 pivot table 생성

crime_station = crime_raw_data.pivot_table(
    crime_raw_data, 
    index = '구분', 
    columns = ['죄종', '발생검거'], 
    aggfunc = [np.sum],
    fill_value = 0
)

crime_station.columns = crime_station.columns.droplevel([0, 1])

crime_station['구별'] = np.nan
crime_station['lat'] = np.nan
crime_station['lng'] = np.nan

crime_station.head()

 

column 확인

crime_station.columns

 

column 합친 후 강의와 같은 column에 넣기

rape_data = crime_station[('강간', '발생')] + crime_station[('강간,추행', '발생')]
rape_catch_data = crime_station[('강간', '검거')] + crime_station[('강간,추행', '검거')]

crime_station[('강간', '발생')] = rape_data
crime_station[('강간', '검거')] = rape_catch_data

 

기존의 강간,추행 column drop

crime_station.drop(columns=[('강간,추행', '발생'), ('강간,추행', '검거')], inplace=True)

crime_station.head()

 

+ 추가 pivot table 생성 전 데이터를 합쳐서 테이블을 생성하는 코드

import numpy as np
import pandas as pd

# 데이터 읽기
crime_raw_data = pd.read_csv('../data/02. crime_in_Seoul.csv', thousands=',', encoding='euc-kr')
# '강간,추행' column name을 '강간'으로 변경
crime_raw_data['죄종'] = crime_raw_data['죄종'].replace('강간,추행', '강간')

# pivot table 생성
crime_station = crime_raw_data.pivot_table(
    crime_raw_data, 
    index = '구분', 
    columns = ['죄종', '발생검거'], 
    aggfunc = [np.sum],
)
# 상단 sum, 건수 column 없애기
crime_station.columns = crime_station.columns.droplevel([0, 1])

crime_station['구별'] = np.nan
crime_station['lat'] = np.nan
crime_station['lng'] = np.nan

crime_station.head()

 


 

반복문으로 Null값 채우기

for idx, rows in crime_station.iterrows():
    station_name = '서울' + str(idx) + '경찰서'
    tmp = gmaps.geocode(station_name, language='ko')
    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
    crime_station.loc[idx, '구별'] = gu.split()[2]

crime_station.head()

 

# 컬럼 level 순서대로 얻어 column 정리하기
crime_station.columns.get_level_values(0)[2]    # 강도
crime_station.columns.get_level_values(1)[2]    # 검거
crime_station.columns.get_level_values(0)[2] + crime_station.columns.get_level_values(1)[2]    # 강도검거
# for문으로 작성
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)))
]
tmp

 

column 교체

crime_station.columns = tmp
crime_station.head()

 

데이터 저장

# 데이터 저장
crime_station.to_csv('../data/02. crime_in_Seoul_raw.csv', sep=',', encoding='utf-8')

 

 


 

구별 데이터로 정리

 

# index_col = index로 사용할 column 설정
crime_anal_station = pd.read_csv('../data/02. crime_in_Seoul_raw.csv', index_col = 0, encoding='utf-8')
crime_anal_station.head()

 

# 구별 데이터를 정리할 pivot table 생성
crime_anal_gu = pd.pivot_table(crime_anal_station, index = '구별', aggfunc=np.sum)

# crime_anal_gu에 필요없는 위치정보 컬럼 lng, lat 삭제하기
crime_anal_gu.drop('lng', axis = 1, inplace = True)
crime_anal_gu.drop('lat', axis = 1, inplace = True)
crime_anal_gu.head()

 

검거율 생성

target = ['강간검거율', '강도검거율', '살인검거율', '절도검거율', '폭력검거율']

num = ['강간검거', '강도검거', '살인검거', '절도검거', '폭력검거']
den = ['강간발생', '강도발생', '살인발생', '절도발생', '폭력발생']

crime_anal_gu[target] = crime_anal_gu[num].div(crime_anal_gu[den].values) * 100

 

# 필요없는 컬럼 제거
crime_anal_gu.drop(['강간검거', '강도검거', '살인검거', '절도검거', '폭력검거'], axis=1, inplace=True)

crime_anal_gu.head()

 

100% 초과한 데이터 조정

# 100보다 큰 숫자 변경하기
crime_anal_gu[crime_anal_gu[target] > 100] = 100

crime_anal_gu.head()

 

column 이름 정리

# 컬럼 이름 변경
crime_anal_gu.rename(
    columns={'강간발생':'강간', '살인발생':'살인', '강도발생':'강도', '절도발생':'절도', '폭력발생':'폭력'}, 
    inplace = True
)
crime_anal_gu.head()

 

 


 

범죄 데이터 정렬을 위한 데이터 정리

 

column의 최고값으로 데이터들을 나눠 0 ~ 1 사이 값으로 정규화

col = ['강간', '강도', '살인', '절도', '폭력']
crime_anal_norm = crime_anal_gu[col] / crime_anal_gu[col].max()
crime_anal_norm.head()

 

검거율 추가하기

# 검거율 추가
col2 = ['강간검거율', '강도검거율', '살인검거율', '절도검거율', '폭력검거율']
crime_anal_norm[col2] = crime_anal_gu[col2]
crime_anal_norm.head()

 

구별 CCTV 자료에서 인구수와 CCTV수 추가

result_CCTV = pd.read_csv('../data/01. CCTV_result.csv', encoding='cp949', index_col='구별')
crime_anal_norm[['인구수', 'CCTV']] = result_CCTV[['인구수', '소계']]

crime_anal_norm.head()

 

범죄 column 추가

# 정규화된 범죄발생 건수 전체의 평균을 구해서 범죄 컬럼 대표값으로 사용
col = ['강간', '강도', '강간', '절도', '폭력']

# axis = 1 : 행 기준 연산, 0 : 열 기준 연산
crime_anal_norm['범죄'] = np.mean(crime_anal_norm[col], axis=1)
crime_anal_norm.head()

 

검거 column 추가

# 검거율의 평균을 구해서 검거 컬럼의 대표값으로 사용

col = ['강간검거율', '강도검거율', '살인검거율', '절도검거율', '폭력검거율']
crime_anal_norm['검거'] = np.mean(crime_anal_norm[col], axis=1)
crime_anal_norm.head()

 

 


 

Seaborn

 

기본 설정

import matplotlib.pyplot as plt
import seaborn as sns
from matplotlib import rc

plt.rcParams['axes.unicode_minus'] = False
rc('font', family='Arial Unicode MS')
get_ipython().run_line_magic('matplotlib', 'inline')

 

set_style() : white, whitegrid, black, blackgrid, sti 설정

x = np.linspace(0, 14, 100)
y1 = np.sin(x)
y2 = 2 * np.sin(x + 0.5)
y3 = 3 * np.sin(x + 1.0)
y4 = 4 * np.sin(x + 1.5)
plt.figure(figsize=(10, 6))
plt.plot(x, y1, x, y2, x, y3, x, y4)
sns.set_style('whitegrid')    # 배경색 / white, whitegrid, dark, darkgrid, sti 등 배경에 관한 설정이 가능하다
# plt.grid()
plt.show()

 

 


 

Seaborn tips data

 

tips 내장 데이터셋

tips = sns.load_dataset('tips')
tips

 

boxplot() : 중앙값, 사분위수, 최솟값, 최댓값, 이상치를 그린다.

# boxplot
plt.figure(figsize=(8, 6))
sns.boxplot(x = tips['total_bill'])
plt.show()

 

boxplot(x, y, data) : x column 그룹별로 y column 데이터를 그린다.

# boxplot
plt.figure(figsize=(8, 6))
sns.boxplot(x ='day', y='total_bill', data=tips)
plt.show()

 

hue : 카테고리 or 이산형 데이터가 들어가며 그룹에 따른 분류를 보여준다.

palette : 색상 설정을 할 수 있다.

# boxplot hue, palette option
# hue : 카테고리 데이터 표현 / palette : 색상 변경

plt.figure(figsize=(8, 6))
sns.boxplot(x='day', y='total_bill', data=tips, hue='smoker', palette='Set2')
plt.show()

 

swarmplot : 산점도로 표현한다.

color : 0 ~ 1의 값을 가지며 1에 가까울수록 흰색, 0에 가까울수록 검정이 된다.

# swarmplot : 산점도로 표현
# color : 1에 가까울 수록 흰색, 0에 가까울수록 검정이 된다.

plt.figure(figsize=(8, 6))
sns.swarmplot(x='day', y='total_bill', data=tips, color='0.2')
plt.show()

 

boxplot, swarmplot

# boxplot with swarmplot

plt.figure(figsize=(8, 6))
sns.boxplot(x='day', y='total_bill', data=tips)
sns.swarmplot(x='day', y='total_bill', data=tips, color='0.25')
plt.show()

 

lmplot : 선형 회귀 모델을 시각화하며 산점도와 회귀선을 통해 선형관계를 파악할 수 있다.

# lmplot : total_bill과 tip 사이 관계 파악

sns.set_style('darkgrid')
sns.lmplot(x='total_bill', y='tip', data=tips, height=7)    # size -> height로 변경됨
plt.show()

 

hue : 카테고리 or 이산형 데이터가 들어가며 그룹에 따른 분류를 보여준다.

# lmplot : total_bill과 tip 사이 관계 파악

sns.set_style('darkgrid')
sns.lmplot(x='total_bill', y='tip', data=tips, height=7, hue='smoker')
plt.show()

 

 

 


 

flights data

 

flights 데이터셋

flights = sns.load_dataset('flights')
flights.head()

 

pivot table 생성

# pivot
# index, columns, values
flights = flights.pivot(index='month', columns='year', values='passengers')
flights.head()

 

heatmap : 2차원 데이터 값을 색상으로 표현하여 시각화한다.

데이터의 상관관계, 빈도, 분포 등을 나타낼 때 유용하다.

# heatmap
# annot = 데이터값 표시 여부 / fmt = 자료형 표현 설정, 'd': 정수, 'f': 실수

plt.figure(figsize=(10, 8))
sns.heatmap(data=flights, annot=True, fmt='d')
plt.show()

 

colormap : 색상 설정

# colormap / 색상설정, 공식홈페이지에 설정 참고
plt.figure(figsize=(10, 8))
sns.heatmap(data=flights, annot=True, fmt='d', cmap='YlGnBu')
plt.show()

 


 

iris data

 

iris 데이터셋

iris = sns.load_dataset('iris')
iris.tail()

 

pairplot : 모든 변수 간 상관관계를 column별 산점도와 히스토그램으로 보여준다.

# pairplot / set_style의 ticks 스타일이 추가된다

sns.set_style('ticks')
sns.pairplot(iris)
plt.show()

 

hue 적용

# hue option

sns.pairplot(iris, hue='species')
plt.show()

 

column 설정

# 원하는 컬럼만 pairplot

sns.pairplot(iris, x_vars = ['sepal_width', 'sepal_length'], y_vars = ['petal_width', 'petal_length'])
plt.show()

 

 


 

anscombe data

 

anscombe 데이터셋

anscombe = sns.load_dataset('anscombe')
anscombe.tail()

 

lmplot

ci : 신뢰구간을 설정한다. 모집단의 모수를 추정할 때 추정치를 얼마나 신뢰할 수 있는지를 나타낸다. 일반적으로 95% 사용

data : dataset column 값이 I인 값만 사용

# ci : 신뢰구간 선택
sns.set_style('darkgrid')
sns.lmplot(x='x', y='y', data=anscombe.query('dataset == "I"'), ci=None, height=7)
plt.show()

 

scatter_kws : 포인트 크기 설정

# scatter_kws : 특정 값에 대한 개별 포인트 크기 설정
sns.set_style('darkgrid')
sns.lmplot(x='x', y='y', data=anscombe.query('dataset == "I"'), ci=None, height=7, scatter_kws={'s':100})
plt.show()

 

order : 회귀선의 차수를 설정한다. 1 : 일차다항식, 2: 이차 다항회귀, 3: 삼차 다항회귀, n: n차 다항회귀

# order option : 1

sns.set_style('darkgrid')
sns.lmplot(
    x='x', 
    y='y', 
    data=anscombe.query('dataset == "II"'), 
    order = 1,
    ci=None, 
    height=7, 
    scatter_kws={'s':100}
)
plt.show()

# order option : 2

sns.set_style('darkgrid')
sns.lmplot(
    x='x', 
    y='y', 
    data=anscombe.query('dataset == "II"'), 
    order = 2,
    ci=None, 
    height=7, 
    scatter_kws={'s':100}
)
plt.show()

 

 

outlier : 이상치. 이상치로 인해 전반적인 경향성이 왜곡될 수 있다.

# outlier 설정

sns.set_style('darkgrid')
sns.lmplot(
    x='x', 
    y='y', 
    data=anscombe.query('dataset == "III"'), 
    ci=None, 
    height=7, 
    scatter_kws={'s':100}
)
plt.show()

 

robust : 이상치나 노이즈가 분석 결과에 미치는 영향을 최소화 시켜준다.

# outlier 설정

sns.set_style('darkgrid')
sns.lmplot(
    x='x', 
    y='y', 
    data=anscombe.query('dataset == "III"'), 
    robust=True,
    ci=None, 
    height=7, 
    scatter_kws={'s':100}
)
plt.show()

 

 


내일의 학습목표

서울시 범죄 검거 현황 4 - 6

 

 

Comments