0. 들어가기에 앞서¶
- 본 Python 프로그래밍 코드는 2022학년 1학기 빅데이터처리와시각화 수업의 기말프로젝트 자료로 사용되었습니다.
- 아래 코드는 어디까지나 참고용으로 사용하시기 바랍니다
In [4]:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
sns.set_theme(style='whitegrid', font_scale=1.5)
sns.set_palette('Set2', n_colors=10)
plt.rc('font', family='malgun gothic')
plt.rc('axes', unicode_minus=False)
import streamlit as st
from datetime import date
In [7]:
# 페이지 제목 및 아이콘 설정
# layout = 'wide'시 그래프가 지나치게 커지는 현상 발생
# 따라서 layout = 'centered'로 표시하여 그래프 크기를 제한함
st.set_page_config(page_title='Safety Index Dashboard',
page_icon='🚓', layout='centered')
st.title("Data App Dashboard")
Out[7]:
DeltaGenerator(_root_container=0, _provided_cursor=None, _parent=None, _block_type=None, _form_data=None)
In [201]:
# 새로고침 설정
if st.button('새로고침'):
st.experimental_rerun()
In [202]:
# 1. 범죄율 표시 실시 (살인, 강도, 강간강제추행, 절도, 폭행)
crime_df = pd.read_csv('전처리_서울시 5대 범죄 발생현황.csv', thousands = ',')
crime_df.head()
Out[202]:
자치구 | 살인_발생 | 살인_검거 | 강도_발생 | 강도_검거 | 강간강제추행_발생 | 강간강제추행_검거 | 절도_발생 | 절도_검거 | 폭력_발생 | 폭력_검거 | |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | 종로구 | 9 | 7 | 7 | 9 | 192 | 855 | 1183 | 944 | 1711 | 1528 |
1 | 중구 | 2 | 2 | 5 | 6 | 186 | 128 | 1642 | 863 | 1576 | 1324 |
2 | 용산구 | 5 | 3 | 6 | 6 | 230 | 186 | 1111 | 534 | 1617 | 1327 |
3 | 성동구 | 5 | 5 | 3 | 3 | 115 | 98 | 1016 | 565 | 1223 | 1103 |
4 | 광진구 | 2 | 2 | 4 | 4 | 255 | 224 | 1664 | 874 | 1676 | 1407 |
In [203]:
# 범죄율 관련 데이터 생성
crime_df.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 25 entries, 0 to 24 Data columns (total 11 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 자치구 25 non-null object 1 살인_발생 25 non-null object 2 살인_검거 25 non-null object 3 강도_발생 25 non-null int64 4 강도_검거 25 non-null int64 5 강간강제추행_발생 25 non-null int64 6 강간강제추행_검거 25 non-null int64 7 절도_발생 25 non-null int64 8 절도_검거 25 non-null int64 9 폭력_발생 25 non-null int64 10 폭력_검거 25 non-null int64 dtypes: int64(8), object(3) memory usage: 2.3+ KB
In [204]:
crime_df['살인_발생'] = crime_df['살인_발생'].replace('-', 0)
crime_df['살인_검거'] = crime_df['살인_검거'].replace('-', 0)
In [205]:
crime_df['살인_발생'] = crime_df['살인_발생'].astype('int')
crime_df['살인_검거'] = crime_df['살인_검거'].astype('int')
In [206]:
state = crime_df.자치구
In [207]:
# 살인
murder_percent = crime_df['살인_발생'] / crime_df['살인_발생'].sum()
murder_percent.sum()
Out[207]:
1.0
In [208]:
# 강도
roberry_percent = crime_df['강도_발생'] / crime_df['강도_발생'].sum()
roberry_percent.sum()
Out[208]:
1.0
In [209]:
# 강간강제추행
rape_percent = crime_df['강간강제추행_발생'] / crime_df['강간강제추행_발생'].sum()
rape_percent.sum()
Out[209]:
1.0
In [210]:
# 절도
thief_percent = crime_df['절도_발생'] / crime_df['절도_발생'].sum()
thief_percent.sum()
Out[210]:
1.0000000000000002
In [211]:
# 폭행
vio_percent = crime_df['폭력_발생'] / crime_df['폭력_발생'].sum()
vio_percent.sum()
Out[211]:
1.0
In [212]:
crime_rate = pd.DataFrame(state)
temp_val = [murder_percent,
roberry_percent,
rape_percent,
thief_percent,
vio_percent]
for i in temp_val:
crime_rate = crime_rate.join(i)
In [213]:
crime_rate.rename({'살인_발생':'살인', '강도_발생':'강도', '강간강제추행_발생' : '강간강제추행', '절도_발생' : '절도', '폭력_발생' : '폭행'}, axis = 1, inplace = True)
In [214]:
crime_rate.head()
Out[214]:
자치구 | 살인 | 강도 | 강간강제추행 | 절도 | 폭행 | |
---|---|---|---|---|---|---|
0 | 종로구 | 0.063830 | 0.050725 | 0.033316 | 0.030893 | 0.035392 |
1 | 중구 | 0.014184 | 0.036232 | 0.032275 | 0.042880 | 0.032600 |
2 | 용산구 | 0.035461 | 0.043478 | 0.039910 | 0.029013 | 0.033448 |
3 | 성동구 | 0.035461 | 0.021739 | 0.019955 | 0.026532 | 0.025298 |
4 | 광진구 | 0.014184 | 0.028986 | 0.044248 | 0.043454 | 0.034668 |
In [350]:
# 누적그래프 표현
def stacked_bar_chart(data, x_range, y_range):
fig, ax = plt.subplots(1, 1, figsize = (15, 10))
if len(y_range) == 0:
return fig
ax.bar(x = x_range, height = y_range[0], data = data)
y_sum = 0
for i in range(len(y_range)-1):
# ax.bar(x = x_range, height = y_range[i + 1], data = data, bottom = y_range[i])
y_sum += data[y_range[i]]
ax.bar(x = x_range,
height = y_range[i + 1],
data = data,
bottom = y_sum)
ax.legend(y_range)
plt.xticks(rotation = 40)
return fig
In [273]:
# bar_graph 표현
def bar_chart(data, x_range, y):
fig, ax = plt.subplots(1, 1, figsize = (15, 10))
ax.bar(x = x_range, height = y, data = data)
plt.xticks(rotation = 40)
return fig
In [217]:
# 제목 : 여성안전데이터 살펴보기
st.header('1. 여성안전데이터 살펴보기')
# 부제목1 : 자치구별 5대범죄 발생율
st.subheader('1.1. 자치구별 5대범죄 발생율')
# 다중선택창1 : 자치구
city_range = st.multiselect(label = '자치구를 선택하십시오',
options = crime_rate['자치구'].unique(),
default = crime_rate['자치구'].unique(),
help = "선택된 자치구의 그래프가 표시됩니다"
)
# 다중선택창2 : 범죄
crime_range = st.multiselect(label = '범죄를 선택하십시오',
options = ['살인', '강도', '강간강제추행', '절도', '폭행'],
default = ['살인', '강도', '강간강제추행', '절도', '폭행'],
help = "선택된 범죄의 범죄율이 그래프로 표시됩니다")
# 다중선택창의 값을 기준으로 데이터를 필터링
temp_crime_df = crime_rate.set_index('자치구')
search_crime_df = temp_crime_df.loc[city_range, crime_range]
# 다중선택창 값을 기준으로 누적(`stacked) 바 플롯을 그린다
plot_df = search_crime_df.reset_index()
fig = stacked_bar_chart(plot_df, city_range, crime_range)
st.pyplot(fig)
Out[217]:
DeltaGenerator(_root_container=0, _provided_cursor=None, _parent=None, _block_type=None, _form_data=None)
In [229]:
std_df = pd.read_csv('pre_2020_서울시_자치구별_가로등개수.csv')
police_df = pd.read_csv('pre_2020_서울시_자치구별_시내주요기관통계_경찰서및지구대.csv')
cctv_df = pd.read_csv('pre_new_서울시_지역별_방범목적_CCTV설치개수.csv')
In [230]:
std_df.head()
Out[230]:
자치구 | 가로등 | |
---|---|---|
0 | 합계 | 283974 |
1 | 종로구 | 8818 |
2 | 중구 | 8550 |
3 | 용산구 | 7838 |
4 | 성동구 | 6266 |
In [231]:
police_df.head()
Out[231]:
자치구 | 경찰서 | 지구대파출소치안센터 | 합계 | |
---|---|---|---|---|
0 | 합계 | 31 | 408 | 439 |
1 | 종로구 | 2 | 22 | 24 |
2 | 중구 | 2 | 18 | 20 |
3 | 용산구 | 1 | 12 | 13 |
4 | 성동구 | 1 | 15 | 16 |
In [232]:
cctv_df.head()
Out[232]:
자치구 | 방범목적 CCTV 개수 | |
---|---|---|
0 | 강남구 | 6107 |
1 | 강동구 | 2082 |
2 | 강북구 | 1826 |
3 | 강서구 | 1983 |
4 | 관악구 | 4642 |
In [233]:
police_df.drop(['경찰서', '지구대파출소치안센터'], axis = 1, inplace = True)
In [245]:
police_df.rename(columns = {'합계' : '치안유지기관'}, inplace = True)
In [247]:
police_df.head()
Out[247]:
자치구 | 치안유지기관 | |
---|---|---|
0 | 합계 | 439 |
1 | 종로구 | 24 |
2 | 중구 | 20 |
3 | 용산구 | 13 |
4 | 성동구 | 16 |
In [248]:
std_df = std_df.merge(police_df, on = '자치구', how = 'inner')
In [250]:
std_df = std_df.merge(cctv_df, on = '자치구', how = 'inner')
In [265]:
std_df.rename(columns = {'방범목적 CCTV 개수' : '방범목적 CCTV'}, inplace = True)
In [266]:
std_df.head()
Out[266]:
자치구 | 가로등 | 치안유지기관 | 방범목적 CCTV | |
---|---|---|---|---|
0 | 종로구 | 8818 | 24 | 1648 |
1 | 용산구 | 7838 | 13 | 1108 |
2 | 광진구 | 4908 | 13 | 2225 |
3 | 동대문구 | 8342 | 21 | 1844 |
4 | 중랑구 | 6521 | 18 | 2960 |
In [288]:
# 부제목1 : 자치구별 5대범죄 발생율
st.subheader('1.2. 치안관련 시설개수 파악')
# 다중선택창1 : 자치구(list)
city_range2 = std_df['자치구'].unique()
# 선택창2 : 치안시설(str)
facility = st.selectbox(label = '개수를 파악할 시설을 선택하십시오',
options =['가로등', '치안유지기관', '방범목적 CCTV'],
index = 0,
help = "선택된 시설의 개수가 표시됩니다")
# 선택창 값을 기준으로 바 플롯을 그린다
fig = bar_chart(std_df, city_range2, facility)
st.pyplot(fig)
Out[288]:
DeltaGenerator(_root_container=0, _provided_cursor=None, _parent=None, _block_type=None, _form_data=None)
In [277]:
pakage_df = pd.read_csv('택배함설치분석결과.csv', encoding = "CP949")
pakage_df.head()
Out[277]:
자치구 | 치안도 | 택배지수 | 여성가구지수 | final_index | 여성안심택배함_총계 | |
---|---|---|---|---|---|---|
0 | 종로구 | 3.98 | 0.889564 | 0.167080 | 4.923356 | 5 |
1 | 중구 | 3.40 | 0.935563 | 0.138612 | 4.325825 | 8 |
2 | 용산구 | 4.02 | 0.741620 | 0.237752 | 5.040628 | 9 |
3 | 성동구 | 5.06 | 0.901464 | 0.263545 | 5.894991 | 10 |
4 | 광진구 | 3.42 | 0.668633 | 0.461396 | 4.289971 | 13 |
In [302]:
len(pakage_df['자치구'].unique())
Out[302]:
25
In [304]:
# 제목 : 2. 분석결과 보고서
st.header('2. 분석결과 보고서')
# 부제목: '2.1. 여성안심택배함 결과보고
st.subheader('2.1. 여성안심택배함 결과보고')
# 다중선택창1 : 자치구
state_range = st.multiselect(label = '자치구를 선택하세요',
options = pakage_df['자치구'].unique(),
default = pakage_df['자치구'].unique())
# 다중선택창2 : index
index_range1 = st.multiselect(label = '그래프에 표시할 지수를 선택하십시오(총합 : final_index)',
options = ['치안도', '택배지수', '여성가구지수'],
default = ['치안도', '택배지수', '여성가구지수'],
help = "치안도 : 5대 범죄발생율을 기준으로 동등한 간격의 수치 부여(0 : 나쁨 ~ 8 : 좋음)\n\n택배지수 : 서울시 자치구별 택배 착지데이터에서 가장 많은 수치를 1로 두고 비율을 설정(0 : 적음 ~ 1 : 많음)\n\n여성가구지수 : 성범죄 피해자 현황의 연령대를 참고하여 여성연령대에 가중치를 부여하여 합산한 후, 가장 많은 수치를 1로 두고 비율을 설정(0 : 적음 ~ 1 : 많음)\n\nfinal_index : 치안도 + (1 - 택배지수) + (1 - 여성가구지수) (0 : 택배설치함 필요 ~ 10 : 택배설치함 불필요)")
# 다중선택창의 값을 기준으로 데이터를 필터링
temp_pakage_df = pakage_df.set_index('자치구')
pakage_search_df = temp_pakage_df.loc[state_range, index_range1]
# 다중선택창 값을 기준으로 누적(`stacked) 바 플롯을 그린다
search_pakage_df = pakage_search_df.reset_index()
fig = stacked_bar_chart(pakage_search_df, state_range, index_range1)
st.pyplot(fig)
Out[304]:
DeltaGenerator(_root_container=0, _provided_cursor=None, _parent=None, _block_type=None, _form_data=None)
In [312]:
package_loc = pd.read_csv('서울시 여성 안심 택배함(안심이) 설치 장소.csv', encoding = 'CP949')
package_loc.head()
Out[312]:
자치구 | 안심 명 | 안심 주소 | WGS x 좌표 | WGS y 좌표 | |
---|---|---|---|---|---|
0 | 중랑구 | 망우3동 공영주차장 | 겸재로61길 40 | 37.591900 | 127.094903 |
1 | 중랑구 | 상봉2동 주민센터 | 동일로 114길 10 | 37.593110 | 127.080900 |
2 | 중랑구 | 면목5동 주민센터 | 동일로 619 | 37.585753 | 127.079474 |
3 | 중랑구 | 면목4동주민센터 | 면목로 246 | 37.574701 | 127.085609 |
4 | 중랑구 | 면목본동 주민센터 | 면목로 397 | 37.587356 | 127.087555 |
In [318]:
package_loc.drop(['안심 명', '안심 주소', '자치구'], axis = 1, inplace = True)
In [324]:
package_loc.rename(columns = {'WGS x 좌표' : 'lat', 'WGS y 좌표' : 'lon'}, inplace = True)
In [325]:
# 여성안심택배함 위치 표시
st.subheader("서울시 여성안심택배함 위치")
st.map(package_loc)
Out[325]:
DeltaGenerator(_root_container=0, _provided_cursor=None, _parent=None, _block_type=None, _form_data=None)
In [326]:
home_df = pd.read_csv('여성안심지킴이집_결과.csv', encoding = "CP949")
home_df.head()
Out[326]:
자치구 | 치안도 | 여성가구지수 | final_index | 여성안심지킴이집_총계 | |
---|---|---|---|---|---|
0 | 종로구 | 3.98 | 0.167080 | 4.812920 | 35 |
1 | 중구 | 3.40 | 0.138612 | 4.261388 | 37 |
2 | 용산구 | 4.02 | 0.237752 | 4.782248 | 34 |
3 | 성동구 | 5.06 | 0.263545 | 5.796455 | 23 |
4 | 광진구 | 3.42 | 0.461396 | 3.958604 | 32 |
In [327]:
# 부제목: '2.1. 여성안심택배함 결과보고
st.subheader('2.2. 여성안심지킴이집 결과보고')
# 다중선택창1 : 자치구
state_range2 = st.multiselect(label = '',
options = home_df['자치구'].unique(),
default = home_df['자치구'].unique())
# 다중선택창2 : index
index_range2 = st.multiselect(label = '그래프에 표시할 지수를 선택하십시오(총합 : final_index)',
options = ['치안도', '여성가구지수'],
default = ['치안도', '여성가구지수'],
help = "치안도 : 5대 범죄발생율을 기준으로 동등한 간격의 수치 부여(0 : 나쁨 ~ 8 : 좋음)\n\n여성가구지수 : 성범죄 피해자 현황의 연령대를 참고하여 여성연령대에 가중치를 부여하여 합산한 후, 가장 많은 수치를 1로 두고 비율을 설정(0 : 적음 ~ 1 : 많음)\n\nfinal_index : 치안도 + (1 - 여성가구지수) (0 : 택배설치함 필요 ~ 9 : 택배설치함 불필요)")
# 다중선택창의 값을 기준으로 데이터를 필터링
temp_home_df = home_df.set_index('자치구')
home_search_df = temp_home_df.loc[state_range2, index_range2]
# 다중선택창 값을 기준으로 누적(`stacked) 바 플롯을 그린다
home_search_df = home_search_df.reset_index()
fig = stacked_bar_chart(home_search_df, state_range2, index_range2)
st.pyplot(fig)
Out[327]:
DeltaGenerator(_root_container=0, _provided_cursor=None, _parent=None, _block_type=None, _form_data=None)
In [345]:
# 주소를 위경도로 변환이 가능하지만
# 주소의 양식이 일정하게 전처리되지 않아
# 위경도값으로 변경이 불가능하다
# 따라서 각 자치구별 안심지킴이집 개수만 파악한다
In [348]:
# 부제목 : 자치구별 여성안심지킴이집 개수
st.subheader('자치구별 여성안심지킴이집 개수')
# 다중선택창1 : 자치구(list)
# 선택창2 : 여성안심지킴이집 총계(str)
home_loc = '여성안심지킴이집_총계'
# 선택창 값을 기준으로 바 플롯을 그린다
fig = bar_chart(home_df, state_range2, home_loc)
st.pyplot(fig)
Out[348]:
DeltaGenerator(_root_container=0, _provided_cursor=None, _parent=None, _block_type=None, _form_data=None)
In [351]:
scout_df = pd.read_csv('여성안심스카우트_결과.csv', encoding = "CP949")
scout_df.head()
Out[351]:
자치구 | 치안도 | 여성가구지수 | final_index | 이용실적 | 스카우트 인원 | 이용실적_비율(%) | |
---|---|---|---|---|---|---|---|
0 | 종로구 | 3.98 | 0.167080 | 4.812920 | 8586 | 14 | 4.828886 |
1 | 중구 | 3.40 | 0.138612 | 4.261388 | 3570 | 16 | 2.007818 |
2 | 용산구 | 4.02 | 0.237752 | 4.782248 | 2981 | 13 | 1.676556 |
3 | 성동구 | 5.06 | 0.263545 | 5.796455 | 8518 | 19 | 4.790641 |
4 | 광진구 | 3.42 | 0.461396 | 3.958604 | 5733 | 13 | 3.224319 |
In [352]:
# 부제목 : 여성안심스카우트 결과보고
st.subheader('2.3. 여성안심스카우트 결과보고')
# 다중선택창1 : 자치구(list)
city_range4 = scout_df['자치구'].unique()
# 선택창2 : 치안시설(str)
value = st.selectbox(label = '데이터를 확인할 항목을 선택하십시오',
options =['final_index', '이용실적', '스카우트 인원', '이용실적_비율(%)'],
index = 0,
help = "final_index의 산출공식은 여성안심지킴이집과 동일합니다")
# 선택창 값을 기준으로 바 플롯을 그린다
fig = bar_chart(scout_df, city_range4, value)
st.pyplot(fig)
Out[352]:
DeltaGenerator(_root_container=0, _provided_cursor=None, _parent=None, _block_type=None, _form_data=None)
In [ ]:
'전문지식 함양 > 학습내용 정리' 카테고리의 다른 글
[대학수업] 텍스트데이터분석2 (0) | 2022.06.28 |
---|---|
[대학수업] 텍스트데이터분석1 (0) | 2022.06.28 |
[대학수업] 빅데이터처리와시각화 python 프로그래밍(분석) (0) | 2022.06.27 |
[대학수업] 빅데이터처리와시각화 (0) | 2022.06.27 |
[공모전] 2021년 KOSAC 대학생 광고대회 참가 후기 (0) | 2021.12.28 |