Ch3 서울시 범죄 현황 데이터 분석 18-32 (범죄3-6)

김민지·2023년 3월 30일
0
  1. seaborn
!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="Malgun Gothic")
%matplotlib inline
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)
# sns.set_style()
# "white", "whitegrid", "dark", "darkgrid"

sns.set_style("white")
plt.figure(figsize=(10, 6))
plt.plot(x, y1, x, y2, x, y3, x, y4)
plt.show()
  • boxplot
tips = sns.load_dataset("tips")
plt.figure(figsize=(8, 6))
sns.boxplot(x="day", y="total_bill", data=tips)
plt.show()
# boxplot hue, palette option
# hue : 카테고리 데이터 표현

plt.figure(figsize=(8, 6))
sns.boxplot(x="day", y="total_bill", data=tips, hue="smoker", palette="Set3") # Set 1-3 (테마)
plt.show()
  • swarmplot
# color : 0~1 사이 검은색부터 흰색 사이 값을 조절

plt.figure(figsize=(8, 6))
sns.swarmplot(x="day", y="total_bill", data=tips, color="0.5")
plt.show()
# 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 : total_bill과 tip 사이 관계 파악

sns.set_style("darkgrid")
sns.lmplot(x="total_bill", y="tip", data=tips, height=7) # size -> height로 바뀜
plt.show()
# hue option

sns.set_style("darkgrid")
sns.lmplot(x="total_bill", y="tip", data=tips, height=7, hue="smoker")
plt.show()
  • heatmap
flights = sns.load_dataset("flights")
# pivot
# index, columns, values

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

plt.figure(figsize=(10, 8))
sns.heatmap(data=flights, annot=True, fmt="d") # annot: 데이터값 표시 여부, fmt: d는 수치를 정수로 표시, f는 실수형
plt.show()
# colormap -> 표시색상테마

plt.figure(figsize=(10, 8))
sns.heatmap(flights, annot=True, fmt="d", cmap="YlGnBu")
plt.show()
  • pairplot : 경향을 보여줌
iris = sns.load_dataset("iris")
# pairplot

sns.set_style("ticks")
sns.pairplot(iris)
# hue option -> 카테고리별로 표시해줌

sns.pairplot(iris, hue="species")
plt.show()
# 원하는 컬럼만 pairplot

sns.pairplot(iris,
             x_vars=["sepal_width", "sepal_length"],
             y_vars=["petal_width", "petal_length"])
plt.show()
  • lmplot
anscombe = sns.load_dataset("anscombe")
sns.set_style("darkgrid")
sns.lmplot(x="x", y="y", data=anscombe.query("dataset == 'I'"), ci=None, height=7, scatter_kws={"s":50})
# scatter_kws : s 점 사이즈 정하기,  ci : 신뢰구간 선택
plt.show()
# order option

sns.set_style("darkgrid")
sns.lmplot(
    x="x",
    y="y",
    data=anscombe.query("dataset == 'II'"),
    order=2,
    ci=None,
    height=7,
    scatter_kws={"s":80})
plt.show()
# 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":80})
plt.show()
  1. 범죄현황 데이터 시각화
# pairplot 강도, 살인 폭력에 대한 상관관계 확인

sns.pairplot(data=crime_anal_norm, vars=["강도", "살인", "폭력"], kind="reg", height=3);
# "인구수", "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", # f:실수형, d:정수형
        linewidths=0.5, # 간격설정
        cmap="RdPu"
    )
    plt.title("범죄 검거 비율(정규화된 검거의 합으로 정렬)")
    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", # 실수형
        linewidths=0.5, # 간격설정
        cmap="RdPu"      
    )
    plt.title("범죄 비율(정규화된 발생 건수로 정렬)")
    plt.show()

drawGraph()
# 데이터 저장

crime_anal_norm.to_csv("../data/02. crime_in_Seoul_final.csv", sep=",", encoding="utf-8")
  1. Folium 지도 시각화
!pip install folium
import folium
import pandas as pd
import json
  • folium.Map()
m = folium.Map(location=[37.5481087,126.9464382], zoom_start=14) # 0 - 18 정도 사용(확대하기)
m
  • save("path")
m.save("./folium.html")
  • tiles option -> 지도 테마 선택
m = folium.Map(
    location=[37.5481087,126.9464382],
    zoom_start=14,
    tiles="Stamen Terrain"
)
m
  • folium.Marker() -> 지도에 마커 생성
m = folium.Map(
    location=[37.5481087,126.9464382],
    zoom_start=14,
    tiles="OpenStreetMap"
)


folium.Marker((37.5524297,126.938971)).add_to(m)

folium.Marker(
    location=[37.5576351,126.9410309],
    popup="Chicken Soup Restaurant"   # 클릭하면 출력됨
).add_to(m)

folium.Marker(
    location=[37.5495876, 126.9318348],
    popup="<i>Starbucks</i>",  # 이탈릭체. 볼드체는 <b></b>
    tooltip="스타벅스"    # 마우스를 갖다대기만 하면 출력됨
).add_to(m)

folium.Marker(
    location=[37.5454653,126.932786],
    popup="<a href='https://zero-base.co.kr/' target=_'blink'>제로베이스</a>",  # 링크로 사이트로 연결됨
    tooltip="라멘트럭"    # 마우스를 갖다대기만 하면 출력됨
).add_to(m)

m
  • folium.Icon() -> 마커 아이콘 모양 설정
m = folium.Map(
    location=[37.5481087,126.9464382],
    zoom_start=14,
    tiles="OpenStreetMap"
)

# icon basic
folium.Marker(
    (37.5524297,126.938971),
    icon=folium.Icon(color="black", icon="info-sign")
).add_to(m)

# icon icon_color
folium.Marker(
    location=[37.5576351,126.9410309],
    popup="Chicken Soup Restaurant", 
    tooltip="icon color",
    icon=folium.Icon(
        color="red",
        icon_color="blue",
        icon="cloud"       
    )
).add_to(m)

# icon custom
folium.Marker(
    location=[37.5495876, 126.9318348],
    popup="<i>Starbucks</i>",  
    tooltip="Icon custom",
    icon=folium.Icon(
        color="purple",
        icon_color="white",
        icon="android",     # 아이콘 모양에 따라 "fa" 혹은 "glyphicon" 둘 중 되는게 있고 안되는게 있음
        angle=50,
        prefix="fa"
    )
).add_to(m)

m
  • folium.ClickForMarker()
    -> 지도 위에 마우스로 클릭할때마다 마커를 생성해줌
    -> popup: str가 있으면 그걸 반환해주고, 없으면 해당 위치의 위도,경도를 반환해줌
m = folium.Map(
    location=[37.5481087,126.9464382],
    zoom_start=14,
    tiles="OpenStreetMap"
)

m.add_child(folium.ClickForMarker(popup="ClickForMarker"))
  • folium.LatLngPopup()
    -> 지도를 마우스로 클릭했을 때 위도 경도 정보를 반환해줌
m = folium.Map(
    location=[37.5481087,126.9464382],
    zoom_start=14,
    tiles="OpenStreetMap"
)
m.add_child(folium.LatLngPopup())
  • folium.Circle(), folium.CircleMarker()
    -> 해당 위치에 동그라미 표시
m = folium.Map(
    location=[37.5481087,126.9464382],
    zoom_start=14,
    tiles="OpenStreetMap"
)

# Circle
folium.Circle(
    location=[37.5501, 126.9527],
    radius=100,
    fill=True,
    color="red",
    fill_color="blue",
    popup="Circle popup",
    tooltip="Circle tooltip"
).add_to(m)

# CircleMarker -> circle보다 훨씬 크기가 크게 나타남. 그 외엔 똑같음
folium.CircleMarker(
    location=[37.5546, 126.9483],
    radius=30,
    fill=True,
    color="blue",
    fill_color="green",
    popup="CircleMarker popup",
    tooltip="CircleMarker tooltip"
).add_to(m)

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

m
  • 서울 아파트 유형 지도 시각화
import pandas as pd
df = pd.read_csv("../data/02. 서울특별시 동작구_주택유형별 위치 정보 및 세대수 현황_20210825.csv", encoding="euc-kr")
# folium

m = folium.Map(location=[37.494495,126.9554905], zoom_start=13)

for idx, row in df.iterrows():
    
    # location
    lat, lng = row.위도, row.경도
    
    # Marker
    folium.Marker(
        location=[lat, lng],
        popup=row.주소,
        tooltip=row.분류,
        icon=folium.Icon(
            icon="home",
            color="lightred" if row.세대수 >= 199 else "lightblue",
            icon_color="darkred" if row.세대수 >= 199 else "darkblue"
        )
    ).add_to(m)
    
    # CircleMarker
    folium.Circle(
        location=[lat, lng],
        radius=row.세대수 * 0.2,   # 세대수에 따라 원의 크기가 정해지도록
        fill=True,
        color="pink" if row.세대수 >= 518 else "green",
        fill_color="pink" if row.세대수 >= 518 else "green"
    ).add_to(m)
    
m
  1. 서울시 범죄현황 지도 시각화
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"
)

folium.Choropleth(
    geo_data=geo_str, # 우리나라 경계선 좌표값이 담긴 데이터
    data=crime_anal_norm["살인"],
    columns=[crime_anal_norm.index, crime_anal_norm["살인"]],
    key_on="feature.id",
    fill_color="PuRd",
    fill_opacity=0.7,
    line_opacity=0.2,
    legend_name="정규화된 살인 발생 건수"
).add_to(my_map)

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

folium.Choropleth(
    geo_data=geo_str, # 우리나라 경계선 좌표값이 담긴 데이터
    data=tmp_criminal,
    columns=[crime_anal_norm.index, tmp_criminal],
    key_on="feature.id",
    fill_color="PuRd",
    fill_opacity=0.7,
    line_opacity=0.2,
    legend_name="인구 대비 범죄 발생 건수"
).add_to(my_map)

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

crime_anal_station = pd.read_csv(
    "../data/02. crime_in_Seoul_raw.csv", encoding="utf-8"
)
crime_anal_station.tail(2)
col = ["살인검거", "강도검거", "강간검거", "절도검거", "폭력검거"]
tmp = crime_anal_station[col] / crime_anal_station[col].max() # 정규화 0-1
crime_anal_station["검거"] = np.mean(tmp, axis=1) # numpy에서는 axis=1 행(가로), axis=0 열(세로) / pandas에서는 axis=1 열(세로), axis=0 행(가로)
crime_anal_station.tail()

-numpy에서는 axis=1 행(가로), axis=0 열(세로)
-pandas에서는 axis=1 열(세로), axis=0 행(가로)

# 경찰서 위치 마커 표시

my_map = folium.Map(
    location=[37.5502, 126.982], zoom_start=11
)

for idx, row in crime_anal_station.iterrows():
    
    folium.Marker(
        location=[row["lat"], row["lng"]]
    ).add_to(my_map)
    
my_map
# 검거에 값을 곱한 뒤 원의 넓이 적용

my_map = folium.Map(
    location=[37.5502, 126.982], zoom_start=11
)

folium.Choropleth(        # 구별 경계선도 같이 표시
    geo_data=geo_str,
    data=crime_anal_norm["범죄"],
    columns=[crime_anal_norm.index, crime_anal_norm["범죄"]],
    key_on="feature.id",
    fill_color="PuRd",
    fill_opacity=0.7,
    line_opacity=0.2
).add_to(my_map)

for idx, row in crime_anal_station.iterrows():
    
    folium.CircleMarker(
        location=[row["lat"], row["lng"]],
        radius=row["검거"] * 50,
        popup=row["구분"] + " : " + "%.2f" % row["검거"],
        color="#3186cc",
        fill=True,
        fill_color="#3186cc"
    ).add_to(my_map)
    
my_map
  1. 서울시 범죄현황 장소별 분석
# 추가 검증

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

crime_loc_raw.tail()
crime_loc_raw.범죄명.unique()

-> array(['살인', '강도', '강간.추행', '절도', '폭력'], dtype=object)

crime_loc_raw["장소"].unique()

-> array(['아파트, 연립 다세대', '단독주택', '노상', '상점', '숙박업소, 목욕탕', '유흥 접객업소', '사무실','역, 대합실', '교통수단', '유원지 ', '학교', '금융기관', '기타'], dtype=object)

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.tail(2)
col = ["살인", "강도", "강간", "절도", "폭력"]
crime_loc_norm = crime_loc / crime_loc.max() # 정규화
crime_loc_norm.head()
crime_loc_norm["종합"] = np.mean(crime_loc_norm, axis=1)
import matplotlib.pyplot as plt
import seaborn as sns
from matplotlib import rc

rc("font", family="Malgun Gothic")
%matplotlib inline
crime_loc_norm_sort = crime_loc_norm.sort_values("종합", ascending=False)

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

drawGraph()

-> 범죄 발생건수를 발생장소에 따라 보여줌

<제로베이스 데이터 취업 스쿨>

0개의 댓글