서울시 범죄 데이터 분석(with folium)

Variety_·2021년 10월 17일
0

Data Analysis

목록 보기
7/10

서울시 범죄현황 데이터 시각화

sns.pairplot(data=crime_anal_norm, vars=['살인','강도','폭력'],kind='reg', height=3)
# reg : regression,

  • 인구수,CCTV와 살인,강도의 상관관계 확인
def drawGraph():
    sns.pairplot(
        data=crime_anal_norm,
        x_vars=['인구수','CCTV'], 
        y_vars=['살인','강도'],
        kind="reg",
        height=4
    )
    plt.show()
  • 인구수, CCTV와 살인검거율,폭력검거율 상관관계 확인
def drawGraph():
    sns.pairplot(
        data=crime_anal_norm,
        x_vars=['인구수','CCTV'], 
        y_vars=['살인검거율','폭력검거율'],
        kind="reg",
        height=4
    )
    plt.show()
  • 검거율 heatmap, '검거' 컬럼을 기준으로 정렬
def drawGraph():
    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=0.5, #간격설정
                cmap="RdPu"
    )
    plt.title("범죄 검거 비율 (정규화된 검거의 합으로 정렬)")
    plt.show()

지도 시각화 (Folium)

  • 현재 사용의 편의성이나 활발한 기능 개선 등으로 Folium이 만족도가 높은 편
  • 기본적으로 크롬에서 원활하게 동작함

기본적으로 그냥 위도, 경도를 알려주면 동작한다. (구글지도에서 우클릭시 위도,경도 나옴)

기본 지도 그리기 : folium.Map(location = [위도, 경도], zoom_size = 크기, tiles="option")

# 지도를 html로 저장가능하다.
지도.svae("./경로/뭐뭐.html")

tiles option : 지도의 스타일 옵션 선택

tiles option

- "OpenStreetMap"
- "Mapbox Bright" (Limited levels of zoom for free tiles)
- "Mapbox Control Room" (Limited levels of zoom for free tiles)
- "Stamen" (Terrain, Toner, and Watercolor)
- "Cloudmade" (Must pass API key)
- "Mapbox" (Must pass API key)
- "CartoDB" (positron and dark_matter)
import folium
import pandas as pd
import json

m = folium.Map(location = [37.54, 127.05],
               zoom_start = 15,
               tiles="OpenStreeMap",) 
#0~18 까지를 권장, 0이 가장 큼
folium.Marker(location=(37.547123, 127.047219169),
              popup = "Subway",
             tooltip = "성수역",
             icon =folium.Icon(color="black", 
                               icon_color = "green",
                               icon = 'bookmark',angle = 50, prefix='fa') ).add_to(m)
m

folium.Marker()

  • Marker : 지도에서 지정한 위치에 마커를 표시해줌
  • folium.Marker(location,popup=option,tooltip=option,icon=option,draggable=option,**kwargs)
    popup : 마커를 누르면 말풍선마냥 팝업창으로 뜸, html문법 적용가능
    tooltip : 마커에 갖다내면 설정문구 뜸, html문법 적용가능
    icon : 마커 아이콘의 꾸밈가능(색깔, 안의 모양) , font-awesome홈피 들어가서 icon탭 - free에서 보이는 것들은 prefix='fa' 설정해줘야 됨
m = folium.Map(
    location=[37.544564958079896, 127.05582307754338], # 성수역 
    zoom_start=14,
    tiles="OpenStreetMap"
) # 0 ~ 18 

# tooltip 
folium.Marker(
    location=[37.544564958079896, 127.05582307754338],
    popup="<b>Subway</b>",
    tooltip="<i>성수역</i>"
).add_to(m)

# html  
folium.Marker(
    location=[37.54558642069953, 127.05729705810472],
    popup="<a href='https://zero-base.co.kr/' target=_'blink'>제로베이스</a>",
    tooltip="<i>Zerobase</i>"
).add_to(m)

# Icon custom 
folium.Marker(
    location=[37.54035903907497, 127.06913328776446], # 건대입구역
    popup="건대입구역",
    tooltip="Icon custom",
    icon=folium.Icon(
        color="purple",
        icon_color="white",
        icon="glyphicon glyphicon-cloud",
        angle=50,
        prefix="glyphicon") # glyphicon
).add_to(m)
m

  • ClickForMarker() : 지도위에 마우스를 클릭했을 때 마커를 생성해 줌, 안에 popup 옵션 설정가능 없으면 위도,경도 반환
m = folium.Map(location = [37.54, 127.05],
               zoom_start = 15,
               tiles="OpenStreetMap")
m.add_child(folium.ClickForMarker())

LatLngPopup() : 지도를 마우스로 클릭했을 때 위도, 경도 반환

m = folium.Map(location = [37.54, 127.05],
               zoom_start = 15,
               tiles="OpenStreetMap")
m.add_child(folium.LatLngPopup())
  • folium.Circle(), folium.CircleMarker()

Circle() :

fill : 안에 색 채우기 여부, color picker로 색깔 고를 수 있음

m = folium.Map(location = [37.54, 127.05],
               zoom_start = 15,
               tiles="OpenStreetMap")
folium.Circle(location=[37.5417,127.0444],
             radius=100,
             fill=True,
             color="#eb9e34",
              fill_color="red",
              popup="circle",
              tooltip="circle"
             ).add_to(m)
m

CircleMarker() : radius가 조금 다르고 나머진 Circle이랑 똑같음

folium.Choropleth

Choropleth() :

import json 
state_data = pd.read_csv("./data/02. US_Unemployment_Oct2012.csv")
m = folium.Map([43, -102], zoom_start=3)

folium.Choropleth(
    geo_data="./data/02. us-states.json", # 경계선 좌표값이 담긴 데이터
    data=state_data, # Series or DataFrame 
    columns=["State", "Unemployment"], # DataFrame columns 
    key_on="feature.id", #json 파일 까봐야함!
    fill_color="BuPu",
    fill_opacity=0.5, # 0~1 
    line_opacity=0.2, # 0~1
    legend_name="Unemployment rate (%)"    
).add_to(m)

m

지도 시각화

import json
import folium
import pandas as pd 
crime_anal_norm = pd.read_csv("./data/02. crime_in_Seoul_final.csv", index_col=0, encoding="utf-8")
geo_path = "./data/02. skorea_municipalities_geo_simple.json"
geo_str = json.load(open(geo_path, encoding="utf-8"))
my_map = folium.Map(location=[37.5502, 126.982], zoom_start=11, tiles="Stamen Toner")

my_map.choropleth(geo_data=geo_str,
                 data=crime_anal_norm["살인"],
                 columns=[crime_anal_norm.index, crime_anal_norm["살인"],],
                 fill_color="PuRd",
                 key_on="feature.id",
                 fill_opacity=0.7,
                 line_opacity=0.2,
                 legend_name="정규화된 살인 발생 건수")
my_map

# 인구 대비 범죄 발생 건수 시각화

tmp_criminal = crime_anal_norm["범죄"] / crime_anal_norm["인구수"]

my_map = folium.Map(location=[37.5502, 126.982], zoom_start=11, tiles="Stamen Toner")

my_map.choropleth(geo_data=geo_str,
                 data=tmp_criminal,
                 columns=[crime_anal_norm.index, tmp_criminal],
                 fill_color="PuRd",
                 key_on="feature.id",
                 fill_opacity=0.7,
                 line_opacity=0.2,
                 legend_name="인구 대비 범죄 발생 건수")
my_map

# 경찰서별 정보를 가지고 범죄발생과 함께 정리

crime_anal_station = pd.read_csv("./data/02. crime_in_Seoul_1st.csv", index_col=0, encoding="utf-8")
col = ["살인검거", "강도검거", "강간검거", "절도검거", "폭력검거"]
tmp = crime_anal_station[col] / crime_anal_station[col].max()
crime_anal_station["검거"] = np.mean(tmp, axis=1)  # numpy 에서 axis=1은 행(가로), pandas에서는 열(세로)
crime_anal_station.head()
# 경찰서 위치를 지도에 표시
my_map = folium.Map(location=[37.5502, 126.982], zoom_start=11)

for idx, rows in crime_anal_station.iterrows():
    folium.Marker([rows["lat"], rows["lng"]]).add_to(my_map)

# 검거율로 동그라미! 
my_map = folium.Map(location=[37.5502, 126.982], zoom_start=11)

for idx, rows in crime_anal_station.iterrows():
    folium.CircleMarker(
        [rows["lat"], rows["lng"]],
        radius=rows["검거"] * 50,
        popup=rows["구분"] + " : " + "%.2f" % rows["검거"],
        color="#3186cc",
        fill=True,
        fill_color="#3186cc").add_to(my_map)
my_map

my_map = folium.Map(location=[37.5502, 126.982], zoom_start=11)
my_map.choropleth(geo_data=geo_str,
                 data=crime_anal_norm["범죄"],
                 columns=[crime_anal_norm.index, crime_anal_norm["범죄"]],
                 fill_color="PuRd",
                 key_on="feature.id",
                 fill_opacity=0.7,
                 line_opacity=0.2)
for idx, rows in crime_anal_station.iterrows():
    folium.CircleMarker(
        [rows["lat"], rows["lng"]],
        radius=rows["검거"] * 50,
        popup=rows["구분"] + " : " + "%.2f" % rows["검거"],
        color="#3186cc",
        fill=True,
        fill_color="#3186cc").add_to(my_map)
    
my_map

  • 강남의 범죄 발생이 많은 것은 혹시 유흥업소의 밀집과 관련이 있지 않을까?
  • 확인을 위해 최초 받았던 장소별 데이터를 읽어보자
crime_loc_raw = pd.read_csv("./data/02. crime_in_Seoul_location.csv", thousands=",", encoding="euc-kr")
crime_loc = crime_loc_raw.pivot_table(crime_loc_raw, index=["장소"], columns=["범죄명"], aggfunc=[np.sum])
crime_loc.columns = crime_loc.columns.droplevel([0, 1])
crime_loc.head()

# 정규화
col = ["살인", "강도", "강간", "절도", "폭력"]
crime_loc_norm = crime_loc / crime_loc.max()
crime_loc_norm.head()

crime_loc_norm["종합"] = np.mean(crime_loc_norm, axis=1)
crime_loc_norm.tail(2)

crime_loc_norm_sort = crime_loc_norm.sort_values(by="종합", ascending=False)

def drawGraph():
    plt.figure(figsize=(10, 10))
    sns.heatmap(crime_loc_norm_sort, annot=True, fmt="f", linewidth=0.5, cmap="RdPu")
    plt.title("범죄와 발생 장소")
    plt.show()
    
drawGraph()

0개의 댓글