나른한 코딩 생활

[9일차] ABC 부트캠프 도로교통공단 데이터로 종합적인 데이터 분석 본문

ABC 부트캠프

[9일차] ABC 부트캠프 도로교통공단 데이터로 종합적인 데이터 분석

GerHerMo 2024. 7. 4. 22:03

사실상 이번주차의 마지막 수업인 9일차가 다가왔다

익일 수업인 10일차에는 ESG 포럼& 세미나 강의를 듣기 때문에

파이썬 실습은 이번주차에 오늘이 마지막이라고 볼 수 있다

 

오늘은 도로교통공단 사망 교통사고 정보를 활용한 지역별 사망교통사고 분석해보자


밑작업

저번과 동일하게 먼저 데이터파일의 준비와 기본적인 install 및 import를 진행하겠다

!pip install koreanize-matplotlibpip
import pandas as pd

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

import folium
import warnings
warnings.filterwarnings('ignore')
df = pd.read_csv('/content/도로교통공단_교통사고 정보_2019.csv',encoding='euc-kr')
df.info() # 불러온 데이터 확인
accident_df = df.copy()
accident_df.head()
accident_df.info()  # 원본 데이터 복사 및 확인

 

기본적인 준비가 끝났으면 먼저 데이터를 전처리 하는 과정이 필요하다

# 사망 교통사고가 가장 많이 발생한 시간은>
# 발생년월일시 -> 시간 추출 -> 뒤에 두자리(00~23) -> 파생 컬럼으로 따로 분리
# 2019010121 -> 21 -> # 분리 할 수 있는 키워드 없음 -> 문자열 슬라이싱

# 1) 문자열 슬라이싱 하고 싶으면 문자열로 타입 변경
accident_df = accident_df.astype({'발생년월일시' : 'string'})
accident_df.info()


# 문자열 말고 % 100 연산으로 끝 뒤를 가져오는건 힘든가?
# -> 할 수 있음!! 여기서는 인덱스를 쓰는 방법을 사용할 뿐
# 2) 시간으로 분리한 데이터를 발생시간 컬럼에 담기
accident_df['발생시간'] = accident_df['발생년월일시'].str[-2:]
# 확인하면 마지막 컬럼 '발생시간'이 생성된 것을 파악 가능

accident_df['발생년월일'] = pd.to_datetime(accident_df['발생년월일시'].str[:-2],
                                      format='%Y%m%d',errors='raise')
del accident_df['발생년월일시'] # 칼럼 삭제 
accident_df.info()

 

수정된 accident_df 의 info

 

위와 같이 '발생시간' 과 '발생년월일' 컬럼을 만들고 '발생년월일시' 컬럼을 삭제 했다 

현재 accident_df 의 컬럼 정렬 상태를 원하는 형태로(파악하기 쉽게) 바꾸기 위해

아래와 같은 코드를 작성했다.

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

# 2-1) 컬럼명을 리스트로 만들기
col1 = accident_df.columns[-2:].to_list()
col1.reverse() # revers() 는 해당 리스트를 뒤집는다

col2 = accident_df.columns[1:-2].to_list()
col_list = col1 + col2
col_list.insert(0,'발생년')

# 2-2) 원하는 컬럼의 순서대로 추출 후 다시 담기
accident_df = accident_df[col_list]

코드 실행 이후 컬럼의 변화(일부분)

 

이렇게 한 데이터파일을 새로운 파일로 저장하는 것도 가능하다

accident_df.to_csv('2019년 사망 교통사고 전처리_20240704.csv',
                   encoding = 'utf-8-sig', index=False)

 


날짜별/시간별 교통사고 현황

이번에는 날짜별/시간별 교통사고 현황 을 scatter를 사용해 출력해보자

fig = px.scatter(accident_df,x= '발생년월일',y='발생시간',
                 size = '사망자수',color='발생지시도')
fig.show()

원의 크기는 사망자수의 크기를 의미한다


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

다음으로는 사망시간별 발생 사망자수를 출력한다

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

 

orientation='h'를 통해 수직으로 그림을 명시해줘야 함


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

발생지역에 따른 사망자 현황을 조사해보자 지역 구분은 자치도와 광역시 크기로 나누었다.

accident_df['발생지시도'].unique()
# 먼저 같은 지역이 다른 명으로 기재되어 있는지 등
# 눈으로 데이터를 파악하는 과정이 꼭 필요하다

 

이렇게 확인 후 이상이 없으면 데이터 상의 지역들에 대한 리스트를 하나 생성한다

해당 변수의 이름은 location_list 라고 선언했다

 

location_list에 대한 

location_list = accident_df['발생지시도'].unique() # 중복제거
location_list.sort() # 해당 리스트를 ㄱㄴㄷ 순으로 정렬

fig = px.bar(accident_df, x = '사망자수',y = '발생지시도',orientation='h',category_orders={'발생지시도':location_list})
fig.show()

category_orders 를 location_list로 설정한 바 그래프이다

 

fig = px.histogram(accident_df, x = '사망자수',y = '발생지시도',
                   orientation='h',text_auto=True,
                   category_orders={'발생지시도':accident_df['발생지시도'].value_counts().index})
fig.show()  # 사건 발생건수로 히스토그램 출력

발생지시도의 값을 센 순 = value_counts 로 정렬


대전광역시 사망 교통사고 데이터 분석 및 시각화

 

앞서 했던 데이터 분석은 전체 데이터를 통해 지역 통합 데이터를 분석하였다

이번에는 특정 지역에 대한 사망 교통사고 데이터를 분석 및 시각화 해보도록 하겠다

 

현재 ABC 부트캠프 수업을 듣고 있는 대전광역시로 설정하였다

dj_df = accident_df.query("발생지시도 == '대전'")

 

dj_df 라는 데이터프레임은 복사한 데이터프레임에서 '발생지시도' 값이

'대전'인 데이터만 가져온 후 대입한 변수이다

 

이제부터는 지금까지 배운 내용을 이용하여 3가지의 주제로 그래프를 출력해보겠다


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

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

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

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

accident_df['발생월'] = accident_df['발생년월일'].dt.month
dj_df['발생월'] = dj_df['발생년월일'].dt.month

fig, axes = plt.subplots(1,2,figsize=(15,5))
plt.suptitle('2019년 월별 교통사고 발생건수 비교')

sns.countplot(data=accident_df,x='발생월',ax=axes[0],
              order=accident_df['발생월'].value_counts().index)

axes[0].set_title('전국')

sns.countplot(data=dj_df,x='발생월',ax=axes[1],
              order=dj_df['발생월'].value_counts().index)

axes[1].set_title('대전')
# 비교하는 차트의 y축 고정하기
plt.ylim(0,accident_df['발생월'].value_counts().max())
plt.show()

좌 : 전국 axes[0] 그래프 / 우 : 대전 axes[1] 그래프 지

 


지도를 활용한 사고 현황 시각화

이번에는 지도를 활용하여 지도상에 마커를 찍어 교통사고 사망자료를 시각화 해보겠다

map = folium.Map(location=[36.321655, 127.378953])

 

위의 location 뒤 두가지의 실수형 값은 대전시청의 위도, 경도 값이다

대전광역시가 표시되는 map 출력

 

이제 본격적으로 지도를 이용하여 사망사고 위치에 CircleMarker를 표출하도록 하겠다

CircleMarker의 사이즈는 총 사상자수를 의미하고

CircleMarker를 클릭하게 되면 popup 이벤트로 사고유형을 표출하도록 하겠다

# CircleMaker 사이즈는 실수형 데이터만 취급
# 사망자수, 부상자수 컬럼 자료형을 실수형으로 형변환

dj_df = dj_df.astype({'사망자수':'float','부상자수':'float'})

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

# 2) CircleMarker 지도에 표출 -> for문을 이용해서 dj_df에 정보가 있을 때까지 지도에 add

for n in dj_df.index:
  # CircleMarker의 사이즈
  cnt = dj_df['사망자수'][n] + dj_df['부상자수'][n]

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

  # 지도에 add 하기
  folium.CircleMarker(location=[lat,lng],radius=cnt*10,
                      popup=dj_df['사고유형'][n], color='red',fill_color='red').add_to(map)

map

위 코드로 생성된 map 의 일부분

 


 

마지막으로 팀프로젝트로 진행했던 특정 구역을 지정한 후 해당 데이터셋을 분석하는 과정 중

내가 맡은 파트인 도로형태 분석을 보겠다

도로형태에 따른 사망자 비율을 파이차트로 표현

us_df = ac_df.query("발생지시도 == '울산'")
# 울산에 대한 데이터 프레임 us_df 생성

 

먼저 기존과 동일하게 전체 데이터 프레임인 ac_df 에서 ( 위 코드들의 accident_df 와 같음 ) 

발생지시도가 울산인 값만 us_df 라는 새로운 데이터 프레임에 저장

 

지난 시간에 성별 월급에 대한 평균통계를 구하는 sex_income 을 참고하여

RoadShape_income 을 구했다.

( 사실 변수명을 RoadShape_income 이 아닌 RoadShape_acc 로 해야했다... )

RoadShape_income  = us_df.groupby('도로형태', as_index=False).agg(dead_sumby =('사망자수','sum'))

 

RoadShape_income의 출력

 

그럼 이제 이렇게 생성된 데이터셋을 px를 통해 파이차트로 나타내기만 하면 된다.

px.pie(RoadShape_income,names='도로형태',values='dead_sumby')

 

파이차트


 

내일은 ESG 포럼 및 세미나 특강이 있다

아쉽게도 유성구까지 가야하기에 조기기상을 해야한다

내일 강연이 어떤 식으로 진행되는지는 모르지만 재밌다고 하니 기대된다