4 분 소요

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

crime_anal_norm.head()
살인 강도 강간 절도 폭력 강간검거율 강도검거율 살인검거율 절도검거율 폭력검거율 인구수 CCTV 범죄 검거
구별
강남구 0.357143 1.000000 1.000000 0.977118 0.733773 80.038760 100.000000 100.000000 53.470867 88.130935 561052 3238 0.813607 84.328112
강동구 0.285714 0.358974 0.310078 0.477799 0.463880 95.000000 92.857143 100.000000 51.425314 86.996047 440359 1010 0.379289 85.255701
강북구 0.500000 0.128205 0.420543 0.332879 0.509351 73.271889 80.000000 85.714286 54.991817 89.344852 328002 831 0.378196 76.664569
관악구 0.428571 0.307692 0.624031 0.572868 0.593143 81.987578 83.333333 100.000000 44.555397 83.678516 520929 2109 0.505261 78.710965
광진구 0.285714 0.282051 0.540698 0.718060 0.438577 83.870968 54.545455 100.000000 40.098634 84.071906 372298 878 0.453020 72.517393

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


“인구수”, “CCTV” 와 “살인검거율”, “폭력검거율”의 상관관계 확인

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


“인구수”, “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()
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", # 실수값으로 표현
        linewidth=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")

folium

folium.Map()

  • location: tuple or list, default None Latitude and Longitude of Map (Northing, Easting).
    m = folium.Map(location=[37.5665512, 126.97805437], zoom_start=18) # 0 ~ 18
    m
    


save(“path”)

m.save("./folium.html")

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) ```py m = folium.Map( location=[37.5665512, 126.97805437], zoom_start=14, # 0 ~ 18 tiles=”openstreetmap” ) folium.Marker((37.56583779,126.97512197)).add_to(m) folium.Marker( location=[37.5665512, 126.97805437], popup=”서울”, tooltip=”서울” ).add_to(m) m

folium.Marker( location=[37.54878936,126.973356], popup=”<a href=’https://zero-base.co.kr/’ target=_‘blink’>제로베이스</a>”, tooltip=”Zerobase” ).add_to(m) m

![](https://velog.velcdn.com/images/yy2hi/post/5cafd53d-8bb5-45a7-bc67-63692167196a/image.png)

---

### folium.Marker()
- 지도에 마커 생성

```py
m = folium.Map(
    location=[37.5665512, 126.97805437],
    zoom_start=14, # 0 ~ 18
    tiles="openstreetmap"
    )
folium.Marker((37.56583779,126.97512197)).add_to(m)
folium.Marker(
    location=[37.5665512, 126.97805437],
    popup="<b>서울</b>",
    tooltip="<i>서울</i>"
).add_to(m)
m

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


folium.Icon()

  • https://www.w3schools.com/bootstrap/bootstrap_ref_comp_glyphs.asp
  • https://fontawesome.com/icons
m = folium.Map(
    location=[37.5665512, 126.97805437],
    zoom_start=13, # 0 ~ 18
    tiles="openstreetmap"
    )

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

# icon _color
folium.Marker(
    (37.54712, 127.047219),
    popup="<b>Subway</b>",
    tooltip="icon_color",
    icon=folium.Icon(
        color="red",
        icon_color="pink",
        icon="cloud"
    )
).add_to(m)

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

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

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

m


folium.ClickForMarker()

  • 지도위에 마우스로 클릭했을 때 마커 생성 ```py m = folium.Map( location=[37.5445, 127.0558], zoom_start=14, tile=”OpenStreetMap” )

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

![](https://velog.velcdn.com/images/yy2hi/post/346920ba-4883-4788-8156-858e9c1fde07/image.png)

---

### folium.LatLngPopup()
- 지도를 마우스로 클릭했을 때 위도 경도 정보 반환
```py
m = folium.Map(
    location=[37.5445, 127.0558],
    zoom_start=14,
    tile="OpenStreetMap"
)

m.add_child(folium.LatLngPopup())


folium.Circle(), folium.CircleMarker()

m = folium.Map(
    location=[37.5445, 127.0558],
    zoom_start=14,
    tile="OpenStreetMap"
)

# Circle
folium.Circle(
    location=[37.5574, 127.04370],
    radius=100,
    fill=True,
    color="#eb9e34",
    fill_color="red",
    popup="Circle Popup",
    tooltip="Circle Tooltip"
).add_to(m)

# CircleMarker
folium.Circle(
    location=[37.5434, 127.04470],
    radius=100,
    fill=True,
    color="#34ebc6",
    fill_color="#c636eb",
    popup="CircleMarker Popup",
    tooltip="CircleMarker Tooltip"
).add_to(m)

m


folium.Choropleth

state_data = pd.read_csv("../data/02. US_Unemployment_Oct2012.csv")
state_data.tail(2)
State Unemployment
48 WI 6.8
49 WY 5.1
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=1, # 0~1
    line_opacity=1, # 0~1
    legend_name="unemployment rate (%)" 
).add_to(m)

m


아파트 유형 지도 시각화

  • 공공데이터포털, https://data.go.kr/data/15066101/fileData.do
df = pd.read_csv("../data/02. 서울특별시 동작구_주택유형별 위치 정보 및 세대수 현황_20210825.csv", encoding="cp949")
df.tail(2)
연번 분류 건물명 행정동 주소 세대수 위도 경도
165 166 연립주택 능내연립 사당5동 서울특별시 동작구 사당로8길 39 22 37.483599 126.968672
166 167 연립주택 천록 대방동 서울특별시 동작구 등용로 43 29 37.505475 126.933434

NaN 데이터 제거

df = df.dropna()
df.info()

=>

<class 'pandas.core.frame.DataFrame'>
Int64Index: 163 entries, 0 to 166
Data columns (total 8 columns):
 #   Column  Non-Null Count  Dtype  
---  ------  --------------  -----  
 0   연번      163 non-null    int64  
 1   분류      163 non-null    object 
 2   건물명     163 non-null    object 
 3   행정동     163 non-null    object 
 4   주소      163 non-null    object 
 5   세대수     163 non-null    int64  
 6   위도      163 non-null    float64
 7   경도      163 non-null    float64
dtypes: float64(2), int64(2), object(4)
memory usage: 11.5+ KB
-------------------------------------------
df = df.reset_index(drop=True)
df.tail(2)
연번 분류 건물명 행정동 주소 세대수 위도 경도
161 166 연립주택 능내연립 사당5동 서울특별시 동작구 사당로8길 39 22 37.483599 126.968672
162 167 연립주택 천록 대방동 서울특별시 동작구 등용로 43 29 37.505475 126.933434
df.columns

=>

Index(['연번 ', '분류 ', '건물명', '행정동', '주소', '세대수', '위도', '경도'], dtype='object')
--------------------------------------------------------------------------
df["연번 "]

=>

0        1
1        2
2        3
3        4
4        5
      ... 
158    163
159    164
160    165
161    166
162    167
Name: 연번 , Length: 163, dtype: int64
-----------------------------------------------------------
df = df.rename(columns={"연번 ": "연번", "분류 ": "분류"})
df.연번[:10]

=>

0     1
1     2
2     3
3     4
4     5
5     6
6     7
7     8
8     9
9    10
Name: 연번, dtype: int64
------------------------
del df["연번"]
df.tail(2)
분류 건물명 행정동 주소 세대수 위도 경도
161 연립주택 능내연립 사당5동 서울특별시 동작구 사당로8길 39 22 37.483599 126.968672
162 연립주택 천록 대방동 서울특별시 동작구 등용로 43 29 37.505475 126.933434
df.describe()
세대수 위도 경도
count 163.000000 163.000000 163.000000
mean 371.920245 37.497442 126.949817
std 413.115354 0.009532 0.019861
min 21.000000 37.477376 126.906940
25% 86.000000 37.490626 126.933284
50% 199.000000 37.496940 126.949902
75% 518.500000 37.505321 126.967196
max 2621.000000 37.514280 126.981966

folium

# folium

m = folium.Map(
    location=[37.497112,126.94437795],
    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="darked" 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