4 분 소요

ABC 부트캠프 [2019 지역별 사망 교통사고 데이터 분석 및 시각화]

image

오늘은 도로교통공단에서 나오는 대한민국의 지역 중

2019년도의 지역별 사망 교통사고를 분석하는 시간을 가졌다.

2019년도에 나는 뭐하고 있었나…

지금이 2023년도니깐 음… 4년전이면 딱 20살 때네

그때로 돌아갈래 . . .

근데 군대 다시가야해서 싫어

2019 지역별 사망 교통사고 데이터 분석

2019년 사망 교통사고 분석

​1. 어느 지역이 가장 많은 사망 교통사고가 발생 했었나

  1. 어느 시간대에 가장 많은 사망 교통사고가 발생 했었나
  2. 교통사고 정보를 지도에 표시하여 시각화

패키지 설치 및 라이브러리 임포트

pip install koreanize-matplotlib   # 한국어 패치
import pandas as pd

import plotly.express as px
import seaborn as sns
import matplotlib.pyplot as plt
import koreanize_matplotlib

import folium

데이터 준비하기

데이터 다운로드 : https://www.data.go.kr/data/15070340/fileData.do

도로교통공단_교통사고 정보_2019.csv

​```python df = pd.read_csv(‘/content/도로교통공단_교통사고 정보_2019.csv’, encoding=’EUC-KR’) df

​
![image](https://github.com/user-attachments/assets/3ea28590-331d-4796-ae83-3a60abe78175)

​
```python
df.info()
# 데이터 개수, 위도/경도 파악, non-null 확인, Dtype: object(문자열)

image

사망교통사고 데이터 전처리

1. 발생년월일시 컬럼에서 시간 컬럼 파생 변수 만들기

# 사망 교통사고가 가장 많이 발생하는 시간은?
# 발생년월일시 -> 뒤에 두자리(시간:00~23) -> 파생변수로 따로 분리
# 2019010100 -> 00 -> 분리할 수 있는 키워드가 없음 -> 문자열 슬라이싱

# 1) 발생년월일시 컬럼은 연속적인 숫자(int) -> 문자열 슬라이딩 할 수 있는 string으로 형변환
df = df.astype({'발생년월일시':'string'})

df.info()

image

발생년월일시가 int형이었다가 -> string 형으로 바뀐 걸 확인

2. 시간으로 분리한 데이터를 발생시간 컬럼으로 닫기

# 2) 시간으로 분리한 데이터를 발생시간 컬럼으로 담기
df['발생시간'] = df['발생년월일시'].str[8:] # str을 한다는건 문자열 형태로 슬라이싱 한다는 말
df.head()

image

위도 컬럼 뒤에 <발생시간>이 생긴 것을 확인

3. 발생시간 컬럼을 숫자 데이터타입으로 변경

# 3) 발생시간 컬럼을 숫자 데이터타입으로 변경
df = df.astype({'발생시간':'int'})
df.info()

image

<발생년월일시> 컬럼에서 <발생년월일> 컬럼 파생 변수 만들기

# 발생년월일시(string) -> 발생년월일(날짜타입)으로 변경
# 2019010119 -> 20190101(년월일) 슬라이싱 ->
# -> YYYY-MM-DD(날짜 형태로 변경) -> 2019-01-01

df['발생년월일'] = pd.to_datetime(df['발생년월일시'].str[:8], format='%Y-%m-%d', errors='raise')
# [:8] 처음부터 8번째까지

df.info()

image

1. 필요없는 컬럼 삭제 및 컬럼 정렬

# 1) 필요없는 컬럼 삭제
del df['발생년월일시']    # 컬럼삭제
df.head()

image

발생년월일시가 사라진 것을 알 수 있다.

2. 컬럼 순서 정리 (발생년, 발생년월일, 발생시간, …)

# 2) 컬럼 순서 정리 발생년, 발생년월일, 발생시간, 주야 ~~~

# 2-1) 컬럼명을 리스트로 만들자
col1 = df.columns[-2:].to_list()    # to_list사용
col1.reverse()
col2 = df.columns[1:-2].to_list()    # 발생년을 제외한 -2 까지만 추출
col_list = col1 + col2
col_list.insert(0, '발생년')      # 0번째에 발생년 삽입

# 2-2) 원하는 컬럼 순서대로 추출
df = df[col_list]
df.columns
Index(['발생년', '발생년월일', '발생시간', '주야', '요일', '사망자수', '부상자수', '중상자수', '경상자수',
       '부상신고자수', '발생지시도', '발생지시군구', '사고유형_대분류', '사고유형_중분류', '사고유형', '가해자법규위반',
       '도로형태_대분류', '도로형태', '가해자_당사자종별', '피해자_당사자종별', '발생위치X_UTMK',
       '발생위치Y_UTMK', '경도', '위도'],
      dtype='object')
​

정제된 데이터 셋 저장하기

df.to_csv('2019년 지역별 교통사고 데이터 전처리.csv', encoding='utf-8-sig', index=False)    # 데이터셋 다운로드

데이터 시각화

1. 날짜별 / 시간별 교통사고 현황보기

fig = px.scatter(df, x='발생년월일', y='발생시간', color='발생지시도', hover_data=['발생시간'])
fig.show()

image

2. 시간대별 교통사고 사망자 현황

fig = px.bar(df, x='사망자수', y='발생시간', orientation='h')
fig.show()

image

19시가 젤 많은 시간으로 알 수 있다 (퇴근시간?)

2-1. 세로 결과 그래프

세로 결과

fig = px.bar(df, x='발생시간', y='사망자수')
fig.show()

image

3. 시도별 교통사고 사망자 현황

location_list = df['발생지시도'].unique()    # 정렬할 때 사용
location_list.sort()
location_list
array(['강원', '경기', '경남', '경북', '광주', '대구', '대전', '부산', '서울', '세종', '울산',
       '인천', '전남', '전북', '제주', '충남', '충북'], dtype=object)
fig = px.bar(df, x='사망자수', y='발생지시도', orientation='h', category_orders={'발생지시도': location_list})
fig.show()

image

17개 지역 중 경기도가 압도적으로 많은 것으로 알 수 있다

3-1. 다른 그래프

plt.figure(figsize=(10,5))     # figure로 크기 조정
sns.countplot(data=df, x='발생지시도', order=location_list)
plt.show()

image

4. 요일별 교통사고 현황

# 사망자 기준
fig = px.bar(df, x='사망자수', y='요일', orientation='h', category_orders={'요일' : ['월', '화', '수', '목', '금', '토', '일']})
fig.show()

image

category_orders를 사용하여 요일별로 순서를 재정리해준다

4-1. 발생한 수 기준

# 발생한 수 기준
plt.figure(figsize=(10,5))     # figure로 크기 조정
sns.countplot(data=df, x='요일', order=['월', '화', '수', '목', '금', '토', '일'])    # order로 정한 순서대로 배치
plt.show()

image

5. 사고 유형별 교통사고 현황

fig = px.bar(df, x='사망자수', y='사고유형', orientation='h')    # 사망자 기준
fig.show()

image

5-1. 다른 그래프

plt.figure(figsize=(20,5))     # figure로 크기 조정
sns.countplot(data=df, x='사고유형')
plt.show()

image

5-2. 가해자 법규 위반

plt.figure(figsize=(15,5))     # figure로 크기 조정
sns.countplot(data=df, x='가해자법규위반')
plt.show()

image

대전광역시 교통사고 발생 데이터 분석

1. 데이터 준비하기

dj_df = df[df['발생지시도']=='대전']    # query문도 가능 / dj_df라는 대전 데이터값 할당
dj_df.info()

2. 발생시간별 교통사고 사망자 현황

# 전국은 19시 가장 많은 사망교통사고 -> 대전은 20시에 발생
fig = px.bar(dj_df, x='사망자수', y='발생시간', orientation='h')
fig.show()

image

전국은 19시가 가장 많지만, 대전은 20시에 가장 많다고 한다.

3. 지역구별 교통사고 사망자 현황

fig = px.bar(dj_df, x='사망자수', y='발생지시군구', orientation='h')
fig.show()

image

서구가 제일 많다고 한다.. 우리집은 동구 ㅎㅎ

4. 요일별 교통사고 사망자 현황

# 전국은 월요일, 금요일 사망 교통사고 발생 -> 대전은 목요일에 가장 많이 발생
fig = px.bar(dj_df, x='사망자수', y='요일', orientation='h')
fig.show()

image

전국은 월/금요일이 가장 많지만, 대전은 목요일이 가장 많이 발생한다고 한다.

5. 사고 유형별 교통사고 사망자 현황

# 전국은 보행중 사망 교통사고 발생 -> 대전도 보행중 가장 많이 발생
fig = px.bar(dj_df, x='사망자수', y='사고유형', orientation='h')
fig.show()

image

대전광역시 사망교통사고 위치 지도 시각화

1. 사망자수에 따른 마커 크기로 시각화

# 사망사고 위치에 CircleMarker 표출
# CircleMarker 사이즈 =  사망자수 + 부상자수(중상자수 + 경상자수 + 부상신고자수)
# CircleMarker 클릭하면, popup으로 사고유형 나타나도록 구현

# CircleMarker 사이즈(radius) -> 실수형 데이터만 취급
# 사망자수, 부상자수 컬럼 데이터타입 -> 실수형으로 변경
dj_df = dj_df.astype({'사망자수':'float', '부상자수':'float'})
dj_df.head()

2. 사망자수+부상자수에 따른 CircleMarker 지도에 표출

# 1) 지도 준비
map = folium.Map(location=[36.35041119, 127.3845475]) # 경도, 위도

# 2) CircleMarker 지도에 표출 -> for문을 이용해서 dj_df 데이터가 있을때까지 CicleMarker 지도에 add
for n in dj_df.index:
  # CircleMarker size -> cnt
  cnt = dj_df['사망자수'][n] + dj_df['부상자수'][n]

  # 위도, 경도 추출
  lat = dj_df['위도'][n]
  lng = dj_df['경도'][n]

  # CircleMarker 지도에 add
  folium.CircleMarker([lat, lng], radius=cnt*10, popup=dj_df['사고유형'][n],   # radius로 Circle이 더 크게 그려짐
                      color='#F70000', fill_color='#F70000').add_to(map)

map

image

대전광역시 사망교통사고 지도 시각화 저장하기

map.save('2019_대전교통사고현황.html')    # html 파일로 저장하기(브라우저로 열기)

마커 표시 된 지도를 html 파일로 저장을 한다.

​—

이렇게 오늘 시간에 전국적으로 발생하는 사망교통사고의 데이터 분석과 함께

대전사람으로써 궁금했던 대전광역시의 교통사고정보를

2019년 당시에 어떠했는지 한 눈에 알 수 있어서 좋은 경험이었다.

오늘 배운 데이터 분석을 활용하여, 나도 얻고자 하는 데이터가 있을 때

데이터가공을 하고 분석하여 나만의 데이터셋을 만들어야 겠다!

댓글남기기