[5주차] Analysis Seoul Crime

목해민·2023년 2월 6일
0

데이터 개요

  • 필요한 모듈 import
  • 먼저 numpy와 pandas를 사용
import numpy as np
import pandas as pd
# 데이터 읽기
crime_raw_data = pd.read_csv("../data/02. crime_in_Seoul.csv",thousands=",",encoding="euc-kr")
# thousands 숫자값을 문자로 인식할 수 있어서 설정
crime_raw_data.head()
  • 숫자값들이 콤마를 사용하고 있어서 문자로 인식될 수 있다.
  • 천단위 구분(thousands=',')이라고 알렺면 콤마를 제거하고 숫자형으로 읽는다.

  • 특정 컬럼에서 unique 조사
  • nan값이 들어있다.

  • 엄청 많은 nan 데이터가 보인다.
  • 이럴때에는 nan을 제거하는 것이 아니라 nan이 아닌 데이터만 다시 가져온다.

Pandas pivot_table

  • Name을 인덱스로 두고 재정렬
    df.pivot_table(index="Name")

  • index를 여러개 지정할 수 있음
    df.pivot_table(index=["Name","Rep","Manager"])

  • values를 지정할 수 있다.
    df.pivot_table(index=["Manager","Rep"], values="Price")

  • values에 함수를 적용할 수 있다.

  • 디폴트는 평균

  • 합산 등의 다른 함수를 적용할 때는 aggfunc 옵션을 지정
    df.pivot_table(index=["Manager","Rep"], values="Price", aggfunc=np.sum)

  • 갯수도 적용(len)
    df.pivot_table(index=["Manager","Rep"], values="Price", aggfunc=[np.sum,len])

  • columns 지정
    df.pivot_table(index=["Manager","Rep"], values="Price",columns="Product", aggfunc=np.sum)

  • Nan값 설정 : fill_value
    df.pivot_table(index=["Manager","Rep"], values="Price",columns="Product", aggfunc=np.sum, fill_value=0)

  • 2개 이상 index, values 설정
    df.pivot_table(index=["Manager","Rep","Product"],values=["Price","Quantity"], aggfunc=np.sum, fill_value=0)

  • aggfunc 2개 이상 설정
    df.pivot_table(index=["Manager","Rep","Product"],
    values=["Price","Quantity"],
    aggfunc=[np.sum,np.mean],
    fill_value=0,
    margins=True) # 총계(ALL)추가

서울시 범죄 현황 데이터 정리

  • 경찰서 이름을 index로 하도록 정리
  • default가 평균(mean)이므로 사건의 합을 기록하기 위해 aggfunc 옵션에 sum을 사용하는 것에 주의
    crime_station = crime_raw_data.pivot_table(
    crime_raw_data,
    index="구분",
    columns=["죄종","발생검거"],
    aggfunc = [np.sum])
    crime_station.head()
  • 이렇게 정리된 데이터의 경우 column이 multi로 잡힌다.

  • pivot_table을 적용하면 column이나 index가 다중으로 잡힌다.

  • multi index에 대한 접근

  • 다중 컬럼에서 특정 컬럼 제거
    crime_station.columns = crime_station.columns.droplevel([0,1])
    crime_station.columns

  • 현재 index는 경찰서 이름으로 되어있다
  • 경찰서 이름으로 구 이름을 알아야 한다

Google Maps API 설치

터미널에 pip install googlemaps 패키지 설치

설치한 후

Python 반복문

pandas에 잘 맞춰진 반복문을 명령 iterrows()

  • Pandas 데이터 프레임은 대부분 2차원
  • 이럴 때 for문을 사용하면, n번째라는 지정을 반복해서 가독률이 떨어짐
  • Pandas 데이터 프레임으로 반복문을 만들 때 iterrows()라는 옵션을 사용하면 편함
  • 받을 때, 인덱스와 내용으로 나누어 받는 것만 주의

Google Maps를 이용한 데이터 정리

import googlemaps

gmaps_key = "발급받은 GEOCODING API KEY값 입력"
gmaps = googlemaps.Client(key=gmaps_key)

  • 구글맵 API에서 데이터 얻기
  • 전체 결과 크기가 1인 list형이라서 tmp[0]로 접근
  • 큰 리스트 안에 dict형이다.
  • dict형에서 데이터를 얻는 get 명령을 사용

  • 경찰서 이름에서 소속된 구 이름 얻기
  • 구 이름과 위도 경도 정보를 저장할 준비
  • 반복문을 이용해서 위 표의 NaN을 모두 채우자
count = 0

# crime_station에서 index(idx)와 나머지(rows)를 받아서 반복문 수행
for idx, rows in crime_station.iterrows():

	# station_name: 구글 검색을 용이하게 하기 위해 검색어를 가급적 상세하게 잡아줌
    station_name = "서울" + str(idx) + "경찰서"
    tmp = gmaps.geocode(station_name, language="ko")
    
    # 앞서 수행한 formatted_address에서 구 이름을 잡는 과정은 그대로
    tmp[0].get("formatted_address")
    tmp_gu = tmp[0].get("formatted_address")
    
    lat = tmp[0].get("geometry")["location"]["lat"]
    lng = tmp[0].get("geometry")["location"]["lng"]
    
    # loc 옵션을 사용
    crime_station.loc[idx, "lat"] = lat
    crime_station.loc[idx, "lng"] = lng
    crime_station.loc[idx, "구별"] = tmp_gu.split()[2]
    # 행(idx)과 열(lat,lng,구별)을 지정해서 구글 검색에서 얻은 정보를 기록
    
    print(count)
    count = count + 1

  • 여기서 두 줄의 컬럼(발생, 강도 검거)을 하나씩 합치는 걸로 하자
  • 예를 들어 강도 검거, 강도 발생

구별 데이터로 정리

  • 경찰서별 데이터로 정리되어 있다

  • 서울은 한 구에 경찰서가 두 곳인 구가 있다

  • 그러므로 구의 이름으로 다시 정렬해야 한다

  • pivot_table을 이용해서 구 별로 정리하자

  • pivot_table의 func을 sum으로 잡자

  • 필요없는 컬럼은 제거(del)

crime_anal_gu = pd.pivot_table(crime_anal_station, index="구별",aggfunc=np.sum)

del crime_anal_gu["lat"]
crime_anal_gu.drop("lng", axis=1, inplace=True)

crime_anal_gu.head()
  • 검거율 생성
# 검거율 생성

# 하나의 컬럼을 다른 컬럼으로 나누기
crime_anal_gu["강도검거"] / crime_anal_gu["강도발생"]

# 다수의 컬럼을 다른 컬럼으로 나누기
crime_anal_gu[["강도검거","살인검거"]].div(crime_anal_gu["강도발생"], axis=0).head(3)

# 다수의 컬럼을 다수의 컬럼으로 각각 나누기

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

crime_anal_gu[num].div(crime_anal_gu[den].values).head()
  • 필요없는 컬럼들 제거 후

  • 작년에서 올해로 넘어오면서 검거했을수도 있어서 검거율이 100이 넘을 수 있다.

  • 하지만 나중에 문제가 될 수 있어서 100 이상의 수치는 100으로 만든다.

# 100보다 큰 숫자 찾아서 바꾸기

crime_anal_gu[crime_anal_gu[target] > 100] = 100
crime_anal_gu.head()

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

  • 검거율까지의 데이터는 잘 정리되었다.

  • 범죄의 경중에 따라 발생 건수의 차이가 크다.

  • 살인은 한 자리 수 발생일 때, 절도는 네 자리수 발생이다.

  • 정규화

  • 본래의 DataFrame은 두고, 정규화된 데이터를 따로 만들기

  • 최고값을 1로 두고, 최소값을 0으로

  • 구별 CCTV자료에서 인구수와 CCTV수 자료 추가
crime_anal_norm[["인구수","CCTV"]] = result_CCTV[["인구수","소계"]]
crime_anal_norm.head()
  • 정규화된 범죄발생 건수 전체의 평균을 구해서 범죄의 대표값으로 사용
# 검거율의 평균을 구해서 검거 컬럼의 대표값으로 사용

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

Seaborn

  • matplotlib가 함께 실행
# !conda install -y seaborn 

import numpy as np 
import pandas as pd 
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") # Windows: Malgun Gothic 
# %matplotlib inline 
get_ipython().run_line_magic("matplotlib", "inline")

boxplot


# boxplot hue, palette option 
# hue: 카테고리 데이터 표현 

plt.figure(figsize=(8, 6))
sns.boxplot(x="day", y="total_bill", data=tips, hue="smoker", palette="Set1") # Set 1 ~ 3 
plt.show()

swarmplot


lmplot

heatmap

# colormap 

plt.figure(figsize=(10, 8))
sns.heatmap(flights, annot=True, fmt="d", cmap="YlGnBu")
plt.show()

pairplot

  • 다수의 컬럼을 비교하는 pairplot

  • hue 옵션 가능

  • 원하는 컬럼만 pairpoint

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

anscombe data






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

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

plt.rcParams["axes.unicode_minus"] = False 
get_ipython().run_line_magic("matplotlib", "inline")
rc("font", family="Arial Unicode MS") # Windows: Malgun Gothic 

# "인구수", "CCTV"와 "살인", "강도"의 상관관계 확인 
# 해석1-1. 인구수가 증가하는 것에 비해 강도가 많이 증가한다고 볼 수는 없다. (아웃라이어도 존재하며, 이를 제외하면 증가폭은 더욱 줄어들 것이다)
# 해석1-2. 강남3구가 인구수가 많은 곳이라면, 강도 발생 비율이 낮으니까 안전하다고 느낄 수 있지 않을까? 
# 해석2-1. 인구수가 증가함에 따라 살인은 증가하는 경향을 보인다. 
# 해석2-2. CCTV가 많이 설치되어있을 수록 강도 사건이 많이 일어난다? 이는 해석의 오류. 그렇다면 CCTV가 많아서 강도사건이 많이 발생하니까, CCTV를 줄여야한다 라고 연결될 수 있다. 
# 해석2-2. 강도 사건이 많이 발생하는 곳에 CCTV를 많이 설치한 것일 수도 있다. 
# 해석2-2. 아웃라이어를 제외하면, 회귀선이 조금 더 내려가서 해석을 달리 할 수 있는 여지가 있다. 

def drawGraph():
    sns.pairplot(
        data=crime_anal_norm, 
        x_vars=["인구수", "CCTV"],
        y_vars=["살인", "강도"],
        kind="reg",
        height=4
    )
    plt.show()
drawGraph()

# "인구수", "CCTV"와 "살인검거율", "폭력검거율"의 상관관계 확인
# 해석1-1. 인구수가 증가할 수록 폭력검거율이 떨어진다. 
# 해석2-1. 인구수와 살인검거율은 조금 높아지는 것 같은 느낌?
# 해석3-1. CCTV와 살인검거율은 해석하기 애매(100에 모여있는 이유는, 검거율은 100으로 제한했기 때문) 
# 해석4-1. CCTV가 증가할수록 폭력검거율이 약간 하향세를 보인다. 

def drawGraph():
    sns.pairplot(
        data=crime_anal_norm, 
        x_vars=["인구수", "CCTV"],
        y_vars=["살인검거율", "폭력검거율"],
        kind="reg",
        height=4
    )
    plt.show()
drawGraph()

# "인구수", "CCTV"와 "절도검거율", "강도검거율"의 상관관계 확인
# 해석1-1. CCTV가 증가할수록 절도검거율이 감소하고 있다. 
# 해석2-1. CCTV가 증가할수록 강도검거율은 증가하고 있다. 

def drawGraph():
    sns.pairplot(
        data=crime_anal_norm, 
        x_vars=["인구수", "CCTV"],
        y_vars=["절도검거율", "강도검거율"],
        kind="reg",
        height=4
    )
    plt.show()
drawGraph()

# 검거율 heatmap 
# "검거" 컬럼을 기준으로 정렬 

def drawGraph():
    
    # 데이터 프레임 생성 
    target_col = ["강간검거율", "강도검거율", "살인검거율", "절도검거율", "폭력검거율", "검거"]
    crime_anal_norm_sort = crime_anal_norm.sort_values(by="검거", ascending=False) # 내림차순 
    
    # 그래프 설정
    plt.figure(figsize=(10, 10))
    sns.heatmap(
        data=crime_anal_norm_sort[target_col],
        annot=True, # 데이터값 표현 
        fmt="f", # d: 정수, f: 실수
        linewidths=0.5, # 간격설정 
        cmap="RdPu",
    )
    plt.title("범죄 검거 비율(정규화된 검거의 합으로 정렬")
    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(
        data=crime_anal_norm_sort[target_col],
        annot=True, # 데이터값 표현 
        fmt="f", # 실수값으로 표현
        linewidths=0.5, # 간격설정
        cmap="RdPu",
    )
    plt.title("범죄 비율(정규화된 발생 건수로 정렬)")
    plt.show()

# 강남구는 살인을 제외하면, 전부 1등 
# 서초구도 상위권에 속함
# 검거율은 낮은데, 범죄 발생 비율이 높다. 
# 강남 송파 서초구가 과연 안전할까? 라는 의문을 계속 가질 수 있음 

drawGraph()

현재까지의 결론

  • 강남 3구의 범죄 발생 건수가 결코 낮지 않다.
  • 강남 3구의 범죄 검거율 조차 높지 않다.
    그러나 인구대비 현황 등을 고려해야 할 것이다.

지도 시각화-Folium

pip install folium
  • Folium 지도 시각화
  • 현재 사용의 편의성이나 활발하 기능 개선 등으로 Folium이 만족도가 높은 편
  • Folium은 기본적으로 크롬에서 동작이 가장 좋음
import folium
import pandas as pd 
import json 

folium.Map()

튜플과 리스트의 형태로. 디폴트값은 없다.

m = folium.Map(location=[37.544564958079896, 127.05582307754338], zoom_start=14) # 0 ~ 18 
m
  • 지도를 html로 저장 가능
m.save("./folium.html")
  • 스타일을 tiles 옵션으로 지정
### 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)
```
m = folium.Map(
    location=[37.544564958079896, 127.05582307754338], 
    zoom_start=14,
    tiles="OpenStreetMap"
) # 0 ~ 18 
m

마커 생성 folium.Marker()

m = folium.Map(
    location=[37.544564958079896, 127.05582307754338], # 성수역 
    zoom_start=14,
    tiles="OpenStreetMap"
) # 0 ~ 18 

# 뚝섬역 
folium.Marker((37.54712311308356, 127.04721916917774)).add_to(m)

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

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

m

folium.Icon()

m = folium.Map(
    location=[37.544564958079896, 127.05582307754338], # 성수역 
    zoom_start=14,
    tiles="OpenStreetMap"
) # 0 ~ 18 

# icon basic  
folium.Marker(
    (37.54712311308356, 127.04721916917774), 
    icon=folium.Icon(color="black", icon='info-sign')
).add_to(m)

# icon icon_color
folium.Marker(
    location=[37.544564958079896, 127.05582307754338],
    popup="<b>Subway</b>",
    tooltip="icon color",
    icon=folium.Icon(
        color="red",
        icon_color="blue",
        icon="cloud")
).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

folium.ClickForMarker()

지도 위에 클릭했을 때 마커 생성

m = folium.Map(
    location=[37.544564958079896, 127.05582307754338], # 성수역 
    zoom_start=14,
    tiles="OpenStreetMap"
) # 0 ~ 18 

m.add_child(folium.ClickForMarker(popup="ClickForMarker"))

folium.LatLngPopup()

지도를 마우스로 클릭했을 때 위도 경도 정보를 반환해줍니다

m = folium.Map(
    location=[37.544564958079896, 127.05582307754338], # 성수역 
    zoom_start=14,
    tiles="OpenStreetMap"
) # 0 ~ 18 

m.add_child(folium.LatLngPopup())

folium.Circle(), folium.CircleMarker()

circle 마커 지원

m = folium.Map(
    location=[37.55068861733562, 127.04420997492151], 
    zoom_start=14,
    tiles="OpenStreetMap"
) # 0 ~ 18 


# Circle 
folium.Circle(
    location=[37.555243442409406, 127.04370422643919], # 한양대학교
    radius=100, 
    fill=True,
    color="#eb9e34",
    fill_color="red",
    popup="Circle Popup",
    tooltip="Circle Tooltip"
).add_to(m)

# CircleMarker
folium.CircleMarker(
    location=[37.54347089498245, 127.04439204503049], # 한양대학교
    radius=100, 
    fill=True,
    color="#34ebc6",
    fill_color="#c634eb",
    popup="CircleMarker Popup",
    tooltip="CircleMarker Tooltip"
).add_to(m)

m

folium.Choropleth

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",
    fill_color="BuPu",
    fill_opacity=0.5, # 0~1 
    line_opacity=0.2, # 0~1
    legend_name="Unemployment rate (%)"    
).add_to(m)

m

# folium 

m = folium.Map(location=[37.50589466533131, 126.93450729567374], zoom_start=13)

for idx, rows in df.iterrows():
    
    # location 
    lat, lng = rows.위도, rows.경도
    
    # Marker 
    folium.Marker(
        location=[lat, lng],
        popup=rows.주소,
        tooltip=rows.분류, 
        icon=folium.Icon(
            icon="home",
            color="lightred" if rows.세대수 >= 199 else "lightblue",
            icon_color="darkred" if rows.세대수 >= 199 else "darkblue",
        )
    ).add_to(m)

    # CircleMarker
    folium.Circle(
        location=[lat, lng],
        radius=rows.세대수 * 0.5, 
        fill=True, 
        color="pink" if rows.세대수 >= 518 else "green",
        fill_color="pink" if rows.세대수 >= 518 else "green",
    ).add_to(m)
    
m   

서울시 범죄 현황에 대한 지도 시각화

import json

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

살인사건

# 2016년 서울시에서 어느정도 살인사건이 있는가?
# 영등포구에서 살인사건이 제일 많이 일어났다

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="정규화된 살인 발생 건수",
)

성범죄

# 강남3구 중 2개 구가 포함되어 있다 

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="정규화된 강간 발생 건수",
)

5대범죄

# 강남구가 역시 포함되어 있다 

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="정규화된 범죄 발생 건수",
)

인구 대비 범죄 발생 건수

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="정규화된 범죄 발생 건수",
)

경찰서별 검거현황과 구별 범죄발생 현황을 표현

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

서울시 범죄 현황 발생 장소 분석

crime_loc_raw = pd.read_csv(
    "../data/02. crime_in_Seoul_location.csv", thousands=",", encoding="euc-kr"
)
crime_loc_raw.head()


# 시각화
crime_loc_norm_sort = crime_loc_norm.sort_values(by="종합", ascending=False)


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

profile
데이터분석가

0개의 댓글