2.6. 데이터프레임 실습 2: 그룹화와 결합#
2일차에서 pandas패키지의 dataframe형태의 데이터에 대해 merge 및 group함수를 이용하여 데이터를 조작하는 법을 설명했다. 이때, 실제 데이터가 아닌 완성된 데이터의 일부를 이용하여 진행했는데, 이번 시간에는 raw data(아무것도 하지 않은 데이터)를 이용하여 원하는 결과를 확인하는 과정을 가지고자 한다.
이번 시간의 목표는 2일차때 사용한 데이터를 화재출동 현황 데이터를 이용하여 생성하는 것이다. 목표는 다음과 같다.
연도별, 시군구별 사망자수, 부상자수, 재산피해금액, 총 출동횟수
연도별, 시군구별 계절(여름, 겨울)에 대한 출동횟수
(1.), (2.)에서 생성한 데이터 합쳐서 전체 데이터 생성
import pandas as pd
화재출동 현황 데이터#
화재출동 현황.csv 파일을 보면, 모든 변수가 영어로 입력되어 있다.
그리고 화재출동 현황_sample.xls 파일을 보면, 이 영어 변수들에 대한 한국어 변수명이 같이 저장되어 있다.
csv파일과 xlsx파일을 같이 읽어, 변수들을 모두 한국어로 바꾸는 작업을 진행해본다.
fire_dat = pd.read_csv("https://uos-bigdata.github.io/lab_data/docs/assets/data_lab_fire/fire.csv")
sample_dat = pd.read_csv("https://uos-bigdata.github.io/lab_data/docs/assets/data_lab_fire/fire_sample.csv")
fire_dat.head()
| wrinvstg_no | fire_type_nm | buld_srtfrm | buld_strctr | buld_srtrf | buld_strct_dong_cnt | ground_nof | bstory_cnt | totar | bottom_area | ... | vhcle_ign_bhf | fld_fire_se | fld_fire_ign_bhf | time_unit_tmprt | time_unit_rainqty | time_unit_ws | time_unit_wd | time_unit_humidity | time_unit_msnf | time_unit | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 170101044118025 | 건축/구조물 | 양식(옥) | 철근콘크리트조 | 슬라브가 | 1.0 | 6.0 | 1.0 | 1133.0 | 168.0 | ... | NaN | NaN | NaN | 0.2 | NaN | 2.2 | 20.0 | 79.0 | NaN | 491 |
| 1 | 170101044947860 | 건축/구조물 | 양식(옥) | 치장벽돌조 | 슬라브가 | 1.0 | 2.0 | 1.0 | 248.0 | 81.0 | ... | NaN | NaN | NaN | -0.7 | NaN | 2.0 | 50.0 | 84.0 | NaN | 436 |
| 2 | 170102110954553 | 건축/구조물 | 양식(옥) | 철근콘크리트조 | 슬라브가 | 1.0 | 3.0 | 1.0 | 1175.0 | 490.0 | ... | NaN | NaN | NaN | -0.7 | NaN | 2.0 | 50.0 | 84.0 | NaN | 436 |
| 3 | 170101162928231 | 건축/구조물 | 양식(옥) | 철근콘크리트조 | 슬라브가 | 1.0 | 12.0 | 1.0 | 8989.0 | 816.0 | ... | NaN | NaN | NaN | 4.0 | NaN | 1.3 | 50.0 | 69.0 | NaN | 433 |
| 4 | 170101140310046 | 기타(쓰레기 화재등) | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | 4.0 | NaN | 1.3 | 50.0 | 69.0 | NaN | 433 |
5 rows × 72 columns
sample_dat.head()
| 조사서번호 | 화재유형명 | 건물구조식 | 건물구조조 | 건물구조즙 | 건물구조동수 | 지상층수 | 지하층수 | 연면적 | 바닥면적 | ... | 차량발화지점 | 임야화재구분 | 임야화재발화지점 | 시간단위기온 | 시간단위강수량 | 시간단위풍속 | 시간단위풍향 | 시간단위습도 | 시간단위적설량 | 시간단위가시거리 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | wrinvstg_no | fire_type_nm | buld_srtfrm | buld_strctr | buld_srtrf | buld_strct_dong_cnt | ground_nof | bstory_cnt | totar | bottom_area | ... | vhcle_ign_bhf | fld_fire_se | fld_fire_ign_bhf | time_unit_tmprt | time_unit_rainqty | time_unit_ws | time_unit_wd | time_unit_humidity | time_unit_msnf | time_unit |
| 1 | 170101044118025 | 건축/구조물 | 양식(옥) | 철근콘크리트조 | 슬라브가 | 1 | 6 | 1 | 1133.000000 | 168.000000 | ... | NaN | NaN | NaN | 0.2 | NaN | 2.2 | 20 | 79 | NaN | 491 |
| 2 | 170101044947860 | 건축/구조물 | 양식(옥) | 치장벽돌조 | 슬라브가 | 1 | 2 | 1 | 248.000000 | 81.000000 | ... | NaN | NaN | NaN | -0.7 | NaN | 2.0 | 50 | 84 | NaN | 436 |
| 3 | 170102110954553 | 건축/구조물 | 양식(옥) | 철근콘크리트조 | 슬라브가 | 1 | 3 | 1 | 1175.000000 | 490.000000 | ... | NaN | NaN | NaN | -0.7 | NaN | 2.0 | 50 | 84 | NaN | 436 |
| 4 | 170101162928231 | 건축/구조물 | 양식(옥) | 철근콘크리트조 | 슬라브가 | 1 | 12 | 1 | 8989.000000 | 816.000000 | ... | NaN | NaN | NaN | 4.0 | NaN | 1.3 | 50 | 69 | NaN | 433 |
5 rows × 72 columns
sample_dat을 살펴보면, 변수명들이 한국어로 되어 있고, 그에 대응되는 영문명들이 1번째 row에 저장되있음을 알 수 있다. 그러므로, 변수명과 1번째 row를 가져와서 데이터로 생성하여 연결하는 것을 진행한다.
col_name = sample_dat.loc[0, :].reset_index()
col_name.columns = ["han_name", 'eng_name']
col_name
| han_name | eng_name | |
|---|---|---|
| 0 | 조사서번호 | wrinvstg_no |
| 1 | 화재유형명 | fire_type_nm |
| 2 | 건물구조식 | buld_srtfrm |
| 3 | 건물구조조 | buld_strctr |
| 4 | 건물구조즙 | buld_srtrf |
| ... | ... | ... |
| 67 | 시간단위풍속 | time_unit_ws |
| 68 | 시간단위풍향 | time_unit_wd |
| 69 | 시간단위습도 | time_unit_humidity |
| 70 | 시간단위적설량 | time_unit_msnf |
| 71 | 시간단위가시거리 | time_unit |
72 rows × 2 columns
han_name 변수는 한국어 변수명, eng_name 변수는 영문 변수명으로 지정하였다. 이 순서는 fire_dat에 있는 변수명과 같은 순서를 가진다. 그러므로 그대로 han_name을 가져와 fire_dat의 변수로 지정해주면 된다.
print(fire_dat.columns)
fire_dat.columns = col_name.iloc[:, 0]
Index(['wrinvstg_no', 'fire_type_nm', 'buld_srtfrm', 'buld_strctr',
'buld_srtrf', 'buld_strct_dong_cnt', 'ground_nof', 'bstory_cnt',
'totar', 'bottom_area', 'buld_sttus_nm', 'dth_cnt', 'injpsn_cnt',
'dth_hnl_dmge_cnt', 'prprty_dmge_amt', 'fire_ocrn_yr', 'season_se_nm',
'qtr_se', 'fire_ocrn_ymd', 'fire_ocrn_tm', 'fire_ocrn_mnth',
'fire_ocrn_day', 'fire_ocrn_hour', 'fire_ocrn_min', 'daywk', 'frstt_nm',
'ward_nm', 'lfdau_nm', 'dsp_reqre_time', 'fire_supesn_time', 'sido_nm',
'sigungu_nm', 'emd_nm', 'cty_frmvl_se_nm', 'emd_se_nm', 'gis_x_axis',
'gis_y_axis', 'longitude', 'la', 'spt_frstt_dist',
'spt_safe_cnter_dist', 'spt_lfdau_dist', 'ign_htsrc_nm',
'ign_htsrc_sclas_nm', 'ign_fctr_lclas_nm', 'ign_fctr_sclas_nm',
'frst_igobj_lclas_nm', 'frst_igobj_sclas_nm', 'ign_mhrls_lclas_nm',
'ign_mhrls_sclas_nm', 'cmbs_expobj_lclas_nm', 'cmbs_expobj_sclas_nm',
'fclty_place_lclas_nm', 'fclty_place_mclas_nm', 'fclty_place_sclas_nm',
'ign_floor_nm', 'soot_area', 'fio_join_trgt_yn', 'frmng_trgt_yn',
'mub_yn', 'emrg_crg_oper_yn', 'vhcle_place', 'vhcle_ign_bhf',
'fld_fire_se', 'fld_fire_ign_bhf', 'time_unit_tmprt',
'time_unit_rainqty', 'time_unit_ws', 'time_unit_wd',
'time_unit_humidity', 'time_unit_msnf', 'time_unit'],
dtype='object')
fire_dat.head()
| han_name | 조사서번호 | 화재유형명 | 건물구조식 | 건물구조조 | 건물구조즙 | 건물구조동수 | 지상층수 | 지하층수 | 연면적 | 바닥면적 | ... | 차량발화지점 | 임야화재구분 | 임야화재발화지점 | 시간단위기온 | 시간단위강수량 | 시간단위풍속 | 시간단위풍향 | 시간단위습도 | 시간단위적설량 | 시간단위가시거리 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 170101044118025 | 건축/구조물 | 양식(옥) | 철근콘크리트조 | 슬라브가 | 1.0 | 6.0 | 1.0 | 1133.0 | 168.0 | ... | NaN | NaN | NaN | 0.2 | NaN | 2.2 | 20.0 | 79.0 | NaN | 491 |
| 1 | 170101044947860 | 건축/구조물 | 양식(옥) | 치장벽돌조 | 슬라브가 | 1.0 | 2.0 | 1.0 | 248.0 | 81.0 | ... | NaN | NaN | NaN | -0.7 | NaN | 2.0 | 50.0 | 84.0 | NaN | 436 |
| 2 | 170102110954553 | 건축/구조물 | 양식(옥) | 철근콘크리트조 | 슬라브가 | 1.0 | 3.0 | 1.0 | 1175.0 | 490.0 | ... | NaN | NaN | NaN | -0.7 | NaN | 2.0 | 50.0 | 84.0 | NaN | 436 |
| 3 | 170101162928231 | 건축/구조물 | 양식(옥) | 철근콘크리트조 | 슬라브가 | 1.0 | 12.0 | 1.0 | 8989.0 | 816.0 | ... | NaN | NaN | NaN | 4.0 | NaN | 1.3 | 50.0 | 69.0 | NaN | 433 |
| 4 | 170101140310046 | 기타(쓰레기 화재등) | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | 4.0 | NaN | 1.3 | 50.0 | 69.0 | NaN | 433 |
5 rows × 72 columns
fire_dat의 변수들이 모두 한국어로 변경되었음을 확인 할 수 있다.
시군구, 연도별 사망자수, 부상자수, 재산피해금액, 출동횟수 계산#
두번째 시간에 일부 시군구, 연도에 대해 groupby를 이용하여 변수에 대한 계산하는 법을 설명했다. 이를 화재출동 현황 데이터에 접목하여 시군구, 연도별로 사망자수, 부상자수, 재산피해금액, 출동횟수를 계산해보자. 이를 위한 순서는 다음과 같다.
먼저 계산할 변수들을 추출한다.
sub_fire_dat = fire_dat.loc[:, ["화재발생연도", "시군구명", "사망수", "부상자수", "재산피해금액"]]
추가적으로 출동횟수를 계산하기 위해, count변수에 1이라는 값을 저장한다. 그 이뉴는
aggmethod를 이용하여sum함수를 한꺼번에 적용하기 위함이다.
sub_fire_dat["count"] = 1
groupby와aggmethod를 이용하여 연도별, 시군구별로 합을 계산한다.
agg_dat = sub_fire_dat.groupby(["화재발생연도", "시군구명"]).agg(["sum"])
agg_dat
| han_name | 사망수 | 부상자수 | 재산피해금액 | count | |
|---|---|---|---|---|---|
| sum | sum | sum | sum | ||
| 화재발생연도 | 시군구명 | ||||
| 2017 | 강남구 | 0 | 11 | 1565258 | 502 |
| 강동구 | 0 | 12 | 418593 | 269 | |
| 강북구 | 0 | 6 | 339146 | 186 | |
| 강서구 | 3 | 22 | 706871 | 364 | |
| 관악구 | 3 | 20 | 654690 | 286 | |
| ... | ... | ... | ... | ... | ... |
| 2021 | 용산구 | 0 | 5 | 296793 | 176 |
| 은평구 | 3 | 8 | 875722 | 160 | |
| 종로구 | 0 | 12 | 465499 | 192 | |
| 중구 | 0 | 16 | 2780374 | 171 | |
| 중랑구 | 1 | 12 | 345257 | 213 |
125 rows × 4 columns
reset_index()method를 이용하여 화재발생연도 및 시군구명을 인덱스에서 가져온다.
agg_dat = agg_dat.reset_index()
agg_dat
| han_name | 화재발생연도 | 시군구명 | 사망수 | 부상자수 | 재산피해금액 | count |
|---|---|---|---|---|---|---|
| sum | sum | sum | sum | |||
| 0 | 2017 | 강남구 | 0 | 11 | 1565258 | 502 |
| 1 | 2017 | 강동구 | 0 | 12 | 418593 | 269 |
| 2 | 2017 | 강북구 | 0 | 6 | 339146 | 186 |
| 3 | 2017 | 강서구 | 3 | 22 | 706871 | 364 |
| 4 | 2017 | 관악구 | 3 | 20 | 654690 | 286 |
| ... | ... | ... | ... | ... | ... | ... |
| 120 | 2021 | 용산구 | 0 | 5 | 296793 | 176 |
| 121 | 2021 | 은평구 | 3 | 8 | 875722 | 160 |
| 122 | 2021 | 종로구 | 0 | 12 | 465499 | 192 |
| 123 | 2021 | 중구 | 0 | 16 | 2780374 | 171 |
| 124 | 2021 | 중랑구 | 1 | 12 | 345257 | 213 |
125 rows × 6 columns
변수명들을 지정해주어 마무리해준다.
agg_dat.columns = ["화재발생연도", "시군구", "사망자수", "부상자수", "재산피해금액", "총출동횟수"]
agg_dat
| 화재발생연도 | 시군구 | 사망자수 | 부상자수 | 재산피해금액 | 총출동횟수 | |
|---|---|---|---|---|---|---|
| 0 | 2017 | 강남구 | 0 | 11 | 1565258 | 502 |
| 1 | 2017 | 강동구 | 0 | 12 | 418593 | 269 |
| 2 | 2017 | 강북구 | 0 | 6 | 339146 | 186 |
| 3 | 2017 | 강서구 | 3 | 22 | 706871 | 364 |
| 4 | 2017 | 관악구 | 3 | 20 | 654690 | 286 |
| ... | ... | ... | ... | ... | ... | ... |
| 120 | 2021 | 용산구 | 0 | 5 | 296793 | 176 |
| 121 | 2021 | 은평구 | 3 | 8 | 875722 | 160 |
| 122 | 2021 | 종로구 | 0 | 12 | 465499 | 192 |
| 123 | 2021 | 중구 | 0 | 16 | 2780374 | 171 |
| 124 | 2021 | 중랑구 | 1 | 12 | 345257 | 213 |
125 rows × 6 columns
계절별 출동횟수 생성#
먼저 계산에 필요한 변수들을 추출 및 생성한다.
sub_fire_dat = fire_dat.loc[:, ["화재발생연도", "시군구명", "계절구분명"]]
sub_fire_dat["count"] = 1
sub_fire_dat
| han_name | 화재발생연도 | 시군구명 | 계절구분명 | count |
|---|---|---|---|---|
| 0 | 2017 | 강남구 | 겨울 | 1 |
| 1 | 2017 | 마포구 | 겨울 | 1 |
| 2 | 2017 | 강서구 | 겨울 | 1 |
| 3 | 2017 | 강동구 | 겨울 | 1 |
| 4 | 2017 | 강북구 | 겨울 | 1 |
| ... | ... | ... | ... | ... |
| 28261 | 2021 | 서대문구 | 겨울 | 1 |
| 28262 | 2021 | 마포구 | 겨울 | 1 |
| 28263 | 2021 | 성북구 | 겨울 | 1 |
| 28264 | 2021 | 은평구 | 겨울 | 1 |
| 28265 | 2021 | 강서구 | 겨울 | 1 |
28266 rows × 4 columns
groupby와aggmethod,sum함수를 이용하여 화재발생연도, 시군구, 계절별로 출동 횟수를 계산한다.
ss_dat = sub_fire_dat.groupby(["화재발생연도", "시군구명", "계절구분명"]).agg('sum')
ss_dat
| han_name | count | ||
|---|---|---|---|
| 화재발생연도 | 시군구명 | 계절구분명 | |
| 2017 | 강남구 | 가을 | 113 |
| 겨울 | 129 | ||
| 봄 | 140 | ||
| 여름 | 120 | ||
| 강동구 | 가을 | 65 | |
| ... | ... | ... | ... |
| 2021 | 중구 | 여름 | 49 |
| 중랑구 | 가을 | 45 | |
| 겨울 | 63 | ||
| 봄 | 46 | ||
| 여름 | 59 |
500 rows × 1 columns
reset_index()method를 이용하여 화재발생연도 및 시군구명을 인덱스에서 가져온다.
ss_dat = ss_dat.reset_index()
ss_dat
| han_name | 화재발생연도 | 시군구명 | 계절구분명 | count |
|---|---|---|---|---|
| 0 | 2017 | 강남구 | 가을 | 113 |
| 1 | 2017 | 강남구 | 겨울 | 129 |
| 2 | 2017 | 강남구 | 봄 | 140 |
| 3 | 2017 | 강남구 | 여름 | 120 |
| 4 | 2017 | 강동구 | 가을 | 65 |
| ... | ... | ... | ... | ... |
| 495 | 2021 | 중구 | 여름 | 49 |
| 496 | 2021 | 중랑구 | 가을 | 45 |
| 497 | 2021 | 중랑구 | 겨울 | 63 |
| 498 | 2021 | 중랑구 | 봄 | 46 |
| 499 | 2021 | 중랑구 | 여름 | 59 |
500 rows × 4 columns
변수명을 할당하여 마무리한다.
ss_dat.columns = ["화재발생연도", "시군구", "계절", "출동횟수"]
ss_dat
| 화재발생연도 | 시군구 | 계절 | 출동횟수 | |
|---|---|---|---|---|
| 0 | 2017 | 강남구 | 가을 | 113 |
| 1 | 2017 | 강남구 | 겨울 | 129 |
| 2 | 2017 | 강남구 | 봄 | 140 |
| 3 | 2017 | 강남구 | 여름 | 120 |
| 4 | 2017 | 강동구 | 가을 | 65 |
| ... | ... | ... | ... | ... |
| 495 | 2021 | 중구 | 여름 | 49 |
| 496 | 2021 | 중랑구 | 가을 | 45 |
| 497 | 2021 | 중랑구 | 겨울 | 63 |
| 498 | 2021 | 중랑구 | 봄 | 46 |
| 499 | 2021 | 중랑구 | 여름 | 59 |
500 rows × 4 columns
이제, 계절별로 데이터가 생성 되었다. 이 데이터 셋에서 계절이 여름, 겨울인 데이터만 추출해 보자.
계절 변수가 “여름” 또는 “겨울”의 값을 가지는 데이터만 추출한다.
tmp_ind = (ss_dat["계절"] == "여름") | (ss_dat["계절"] == "겨울")
sub_ss_dat = ss_dat.loc[tmp_ind, :]
sub_ss_dat
| 화재발생연도 | 시군구 | 계절 | 출동횟수 | |
|---|---|---|---|---|
| 1 | 2017 | 강남구 | 겨울 | 129 |
| 3 | 2017 | 강남구 | 여름 | 120 |
| 5 | 2017 | 강동구 | 겨울 | 63 |
| 7 | 2017 | 강동구 | 여름 | 73 |
| 9 | 2017 | 강북구 | 겨울 | 51 |
| ... | ... | ... | ... | ... |
| 491 | 2021 | 종로구 | 여름 | 54 |
| 493 | 2021 | 중구 | 겨울 | 41 |
| 495 | 2021 | 중구 | 여름 | 49 |
| 497 | 2021 | 중랑구 | 겨울 | 63 |
| 499 | 2021 | 중랑구 | 여름 | 59 |
250 rows × 4 columns
데이터의 형태를 보면, 계절이란 변수에 “여름”, “겨울”로써 값이 들어가 있음을 알 수 있다. 그러므로 이를 변수의 형태로 변환하기 위해 다음과 같은 작업을 진행한다.
계절이 “여름”인 데이터들만 가져오고, 이 데이터의 출동횟수를 “출동횟수_여름”으로 할당한다.
tmp_ind = sub_ss_dat["계절"] == "여름"
sum_dat = sub_ss_dat.loc[tmp_ind, :].drop(["계절"], axis = 1)
sum_dat.columns = ["화재발생연도", "시군구", "출동횟수_여름"]
sum_dat
| 화재발생연도 | 시군구 | 출동횟수_여름 | |
|---|---|---|---|
| 3 | 2017 | 강남구 | 120 |
| 7 | 2017 | 강동구 | 73 |
| 11 | 2017 | 강북구 | 41 |
| 15 | 2017 | 강서구 | 81 |
| 19 | 2017 | 관악구 | 69 |
| ... | ... | ... | ... |
| 483 | 2021 | 용산구 | 36 |
| 487 | 2021 | 은평구 | 42 |
| 491 | 2021 | 종로구 | 54 |
| 495 | 2021 | 중구 | 49 |
| 499 | 2021 | 중랑구 | 59 |
125 rows × 3 columns
계절이 “겨울”인 데이터들만 가져오고, 이 데이터의 출동횟수를 “출동횟수_겨울”으로 할당한다.
tmp_ind = sub_ss_dat["계절"] == "겨울"
win_dat = sub_ss_dat.loc[tmp_ind, :].drop(["계절"], axis = 1)
win_dat.columns = ["화재발생연도", "시군구", "출동횟수_겨울"]
win_dat
| 화재발생연도 | 시군구 | 출동횟수_겨울 | |
|---|---|---|---|
| 1 | 2017 | 강남구 | 129 |
| 5 | 2017 | 강동구 | 63 |
| 9 | 2017 | 강북구 | 51 |
| 13 | 2017 | 강서구 | 89 |
| 17 | 2017 | 관악구 | 82 |
| ... | ... | ... | ... |
| 481 | 2021 | 용산구 | 47 |
| 485 | 2021 | 은평구 | 57 |
| 489 | 2021 | 종로구 | 48 |
| 493 | 2021 | 중구 | 41 |
| 497 | 2021 | 중랑구 | 63 |
125 rows × 3 columns
두 개의 데이터 셋 결합#
다음, pandas패키지의 merge함수를 이용하여 화재발생연도, 시군구 기준으로 조인을 진행한다.
sum_win_dat = pd.merge(sum_dat, win_dat, on = ["화재발생연도", "시군구"])
sum_win_dat
| 화재발생연도 | 시군구 | 출동횟수_여름 | 출동횟수_겨울 | |
|---|---|---|---|---|
| 0 | 2017 | 강남구 | 120 | 129 |
| 1 | 2017 | 강동구 | 73 | 63 |
| 2 | 2017 | 강북구 | 41 | 51 |
| 3 | 2017 | 강서구 | 81 | 89 |
| 4 | 2017 | 관악구 | 69 | 82 |
| ... | ... | ... | ... | ... |
| 120 | 2021 | 용산구 | 36 | 47 |
| 121 | 2021 | 은평구 | 42 | 57 |
| 122 | 2021 | 종로구 | 54 | 48 |
| 123 | 2021 | 중구 | 49 | 41 |
| 124 | 2021 | 중랑구 | 59 | 63 |
125 rows × 4 columns
마지막으로, 처음에 생성시킨 화재발생연도, 시군구 별 사망자수, 부상자수, 재산피해금액, 총출동횟수에 대한 데이터와 똑같은 변수(화재발생연도, 시군구)를 기준으로 pandas패키지의 merge 함수를 이용하여 결합한다.
final_dat = pd.merge(agg_dat, sum_win_dat, on = ["화재발생연도", "시군구"])
final_dat
| 화재발생연도 | 시군구 | 사망자수 | 부상자수 | 재산피해금액 | 총출동횟수 | 출동횟수_여름 | 출동횟수_겨울 | |
|---|---|---|---|---|---|---|---|---|
| 0 | 2017 | 강남구 | 0 | 11 | 1565258 | 502 | 120 | 129 |
| 1 | 2017 | 강동구 | 0 | 12 | 418593 | 269 | 73 | 63 |
| 2 | 2017 | 강북구 | 0 | 6 | 339146 | 186 | 41 | 51 |
| 3 | 2017 | 강서구 | 3 | 22 | 706871 | 364 | 81 | 89 |
| 4 | 2017 | 관악구 | 3 | 20 | 654690 | 286 | 69 | 82 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 120 | 2021 | 용산구 | 0 | 5 | 296793 | 176 | 36 | 47 |
| 121 | 2021 | 은평구 | 3 | 8 | 875722 | 160 | 42 | 57 |
| 122 | 2021 | 종로구 | 0 | 12 | 465499 | 192 | 54 | 48 |
| 123 | 2021 | 중구 | 0 | 16 | 2780374 | 171 | 49 | 41 |
| 124 | 2021 | 중랑구 | 1 | 12 | 345257 | 213 | 59 | 63 |
125 rows × 8 columns
2일차때 연습으로 사용한 데이터는 이렇게 생성됩니다. 그리고, 최종으로 엑셀로 저장은 다음과 같다.
final_dat.to_csv("practice_dat.csv", index = False)
추가적인 내용#
일반적으로 위 final_dat의 데이터를 얻으면 다음과 같은 사항에 대해 궁금증을 가질 수 있다.
연도, 시군구별 사망자수, 부상자수, 재산피해금액 각 변수들에 대해 가장 높은지역은 어딜까??
여름은 겨울보다 습하고, 겨울은 여름보다 습하다. 그러므로, 화재 사건에 대해서는 겨울에 더 많이 발생할 가능성이 높다고 생각 할 수 있다. 이를 실제로 확인하기 위해 연도별로 여름, 겨울의 출동횟수의 차이를 계산해보자.
1.)을 확인하기 위해, 연도에 대한 데이터 셋을 생성하자.
year_ind = final_dat["화재발생연도"] == 2021
year_dat = final_dat.loc[year_ind, :]
먼저, 사망자수가 가장 높은 지역이다. 이는 year_dat에서 사망자수의 최댓값과 사망자수가 같은 index를 찾아 추출하면된다.
max_ind = year_dat["사망자수"] == year_dat['사망자수'].max()
year_dat.loc[max_ind, :]
| 화재발생연도 | 시군구 | 사망자수 | 부상자수 | 재산피해금액 | 총출동횟수 | 출동횟수_여름 | 출동횟수_겨울 | |
|---|---|---|---|---|---|---|---|---|
| 102 | 2021 | 강북구 | 5 | 14 | 410205 | 146 | 38 | 29 |
같은 방법으로 부상자수, 재산피해금액, 총출동횟수는 각각 다음과 같다.
max_ind = year_dat["부상자수"] == year_dat['부상자수'].max()
year_dat.loc[max_ind, :]
| 화재발생연도 | 시군구 | 사망자수 | 부상자수 | 재산피해금액 | 총출동횟수 | 출동횟수_여름 | 출동횟수_겨울 | |
|---|---|---|---|---|---|---|---|---|
| 116 | 2021 | 성북구 | 4 | 46 | 493231 | 168 | 37 | 56 |
max_ind = year_dat["재산피해금액"] == year_dat['재산피해금액'].max()
year_dat.loc[max_ind, :]
| 화재발생연도 | 시군구 | 사망자수 | 부상자수 | 재산피해금액 | 총출동횟수 | 출동횟수_여름 | 출동횟수_겨울 | |
|---|---|---|---|---|---|---|---|---|
| 123 | 2021 | 중구 | 0 | 16 | 2780374 | 171 | 49 | 41 |
max_ind = year_dat["총출동횟수"] == year_dat['총출동횟수'].max()
year_dat.loc[max_ind, :]
| 화재발생연도 | 시군구 | 사망자수 | 부상자수 | 재산피해금액 | 총출동횟수 | 출동횟수_여름 | 출동횟수_겨울 | |
|---|---|---|---|---|---|---|---|---|
| 100 | 2021 | 강남구 | 2 | 15 | 1354949 | 391 | 91 | 112 |
2.)를 확인하기 위해 여름의 출동횟수와 겨울의 출동횟수를 계산해보자.
final_dat["출동횟수_차이"] = final_dat["출동횟수_겨울"] - final_dat["출동횟수_여름"]
final_dat
| 화재발생연도 | 시군구 | 사망자수 | 부상자수 | 재산피해금액 | 총출동횟수 | 출동횟수_여름 | 출동횟수_겨울 | 출동횟수_차이 | |
|---|---|---|---|---|---|---|---|---|---|
| 0 | 2017 | 강남구 | 0 | 11 | 1565258 | 502 | 120 | 129 | 9 |
| 1 | 2017 | 강동구 | 0 | 12 | 418593 | 269 | 73 | 63 | -10 |
| 2 | 2017 | 강북구 | 0 | 6 | 339146 | 186 | 41 | 51 | 10 |
| 3 | 2017 | 강서구 | 3 | 22 | 706871 | 364 | 81 | 89 | 8 |
| 4 | 2017 | 관악구 | 3 | 20 | 654690 | 286 | 69 | 82 | 13 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 120 | 2021 | 용산구 | 0 | 5 | 296793 | 176 | 36 | 47 | 11 |
| 121 | 2021 | 은평구 | 3 | 8 | 875722 | 160 | 42 | 57 | 15 |
| 122 | 2021 | 종로구 | 0 | 12 | 465499 | 192 | 54 | 48 | -6 |
| 123 | 2021 | 중구 | 0 | 16 | 2780374 | 171 | 49 | 41 | -8 |
| 124 | 2021 | 중랑구 | 1 | 12 | 345257 | 213 | 59 | 63 | 4 |
125 rows × 9 columns
출동횟수_차이의 의미는 이 값이 0보다 크다면 겨울의 출동횟수가 많다는 것이고, 0보다 작으면 여름의 출동횟수가 많다는 것이다. 그러므로, 0보다 큰것의 횟수를 계산하면 된다.
final_dat["count"] = final_dat["출동횟수_차이"] > 0
final_dat.groupby("화재발생연도")["count"].agg('sum')
화재발생연도
2017 15
2018 15
2019 14
2020 14
2021 16
Name: count, dtype: int64
서울은 25개 시군구이고, 모두 13보다 큰 값을 가진다. 이 결과로써 실제로, 여름보다 겨울의 출동횟수가 더 큰 지역이 절반 이상의 지역임을 알 수 있다.