항공기 사고에서 배우는 교훈: 제주항공 사고를 돌아보며 파이썬으로 살펴보기

2024년 12월 29일 우리는 제주항공 사고라는 비극적인 소식에 충격을 받았습니다. 이 어려운 시기에 피해자들과 그 가족들에게 깊은 애도를 표합니다.
이번 포스트는 사고로 깊은 슬픔에 잠긴 분들을 기리며, 데이터를 기반으로 한 통찰을 통해 항공기 사고를 분석하고 교훈을 얻고자 합니다. 함께 성찰하고 배우며 더 안전한 미래를 만들어 나갔으면 하는 바램으로 글을 작성해 봅니다.
항공기 사고 데이터 개요
이 포스트에서 사용한 Kaggle 항공기 사고 데이터셋은 항공 사고와 관련된 다양한 정보를 담고 있으며, 데이터 분석 및 안전 개선 연구를 위한 중요한 자료입니다. 데이터셋의 주요 특징은 다음과 같습니다:
데이터셋 이름은 Aviation Accident Database Synopses 로, 미국 National Transportation Safety Board (NTSB)의 항공 사고 데이터베이스를 바탕으로 제공됩니다. 참고로 세부적인 데이터셋 내용은 Aviation Accident Database Synopses on Kaggle 를 참고하시기 바랍니다.
Kaggle 데이터셋 개요 요약
항목 | 설명 |
---|---|
데이터셋 이름 | Aviation Accident Database Synopses |
출처 | 미국 NTSB (National Transportation Safety Board) |
라이센스 | CC0 1.0 Universal |
주요 열 | – Event_Date : 사고 날짜 |
– Location , Country : 사고 위치 | |
– Broad.phase.of.flight : 운항 단계 | |
– Weather.Condition : 기상 조건 | |
– Total.Fatal.Injuries : 사망자 수 | |
– Probable_Cause : 사고 원인 | |
사용 목적 | – 사고 경향 분석, 기술 개선, 정책 개발 |
데이터셋 특징
- 사고 발생 시기 및 위치: 사고 연도와 장소별로 데이터를 시각화하여 패턴 분석 가능.
- 운항 단계별 사고: 특정 단계(예: 착륙, 이륙)에서의 사고 경향 파악.
- 피해 규모: 사망자, 부상자, 생존자 수를 통해 사고 심각도 평가.
이 데이터셋은 항공기 사고를 분석하고 여객기 사고와 같은 대형참사를 예방하기 위한 실질적인 인사이트를 제공합니다.
파이썬 시각화로 항공기 사고 데이터 분석하기
파이썬은 복잡한 데이터 세트 내에서 통찰력을 발견하도록 연구원과 분석가를 지원하는 다재다능한 프로그래밍 언어입니다. 파이썬 시각화로 항공기 사고를 분석하면 정책 결정 및 기술적 개선을 위한 패턴과 이상값을 식별할 수 있습니다.
아래는 항공기 사고 데이터를 파이썬 시각화 코드 스니펫입니다. 이 분석은 최근 제주항공 사고와 같은 참사에 기여했을 수 있는 경향을 심층적으로 이해하는 데 도움을 줄 수 있습니다. 코드가 길기는 하지만 마무리 섹션의 코드 상세해설에 이해하기 쉽게 풀어두었으니 참고하시기 바랍니다.
# Kaggle API 설정 및 데이터 다운로드
!pip install kaggle -q # Kaggle 라이브러리 설치
import os
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
import plotly.express as px
# Kaggle API key 설정
os.environ['KAGGLE_CONFIG_DIR'] = '/content' # 현재 디렉토리로 설정
!chmod 600 /content/kaggle.json # 권한 설정
# Kaggle 데이터셋 다운로드
!kaggle datasets download -d khsamaha/aviation-accident-database-synopses -p /content/aviation_data --unzip
# 데이터 로드
file_path = "/content/aviation_data/AviationData.csv"
df = pd.read_csv(file_path, encoding='ISO-8859-1', low_memory=False)
# 열 이름 확인 및 수정
df.rename(columns={"Event Date": "Event_Date", "Broad.phase.of.flight": "Phase_of_Flight"}, inplace=True)
# 날짜 변환 및 연도 생성
df.rename(columns={'Event.Date': 'Event_Date'}, inplace=True)
df['Event_Date'] = pd.to_datetime(df['Event_Date'], errors='coerce')
df['Year'] = df['Event_Date'].dt.year
# 결측치가 있는 행 제거
df = df.dropna(subset=['Phase_of_Flight'])
# 운항 단계별 사고 건수 계산
phase_counts = (
df.groupby(['Phase_of_Flight', 'Year'])
.size()
.reset_index(name='count')
)
# matplotlib 기본 폰트 설정 (경고 방지)
plt.rcParams['font.family'] = 'DejaVu Sans' # Colab에서 기본적으로 지원되는 폰트
# 1. Total accidents by phase of flight (Bar Chart)
plt.figure(figsize=(12, 6))
total_by_phase = phase_counts.groupby('Phase_of_Flight')['count'].sum().sort_values()
sns.barplot(x=total_by_phase.values, y=total_by_phase.index, palette='viridis')
plt.title('Total Accidents by Phase of Flight')
plt.xlabel('Number of Accidents')
plt.ylabel('Phase of Flight')
plt.tight_layout()
plt.show()
# 2. Annual accident trends by phase of flight (Line Chart)
plt.figure(figsize=(15, 8))
for phase in phase_counts['Phase_of_Flight'].unique():
phase_data = phase_counts[phase_counts['Phase_of_Flight'] == phase]
plt.plot(phase_data['Year'], phase_data['count'], marker='o', label=phase)
plt.title('Annual Accident Trends by Phase of Flight')
plt.xlabel('Year')
plt.ylabel('Number of Accidents')
plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
# 3. Heatmap of accidents by year and phase of flight
pivot_data = phase_counts.pivot(index='Phase_of_Flight', columns='Year', values='count')
plt.figure(figsize=(15, 8))
sns.heatmap(pivot_data, cmap='viridis', cbar_kws={'label': 'Number of Accidents'})
plt.title('Accidents by Year and Phase of Flight (Heatmap)')
plt.xlabel('Year')
plt.ylabel('Phase of Flight')
plt.tight_layout()
plt.show()
# 4. Accident proportion by phase of flight (Last 10 years - Interactive Pie Chart)
max_year = df['Year'].max()
recent_data = df[df['Year'] >= max_year - 10]
recent_counts = (
recent_data.groupby('Phase_of_Flight')
.size()
.reset_index(name='count')
)
recent_counts['percentage'] = recent_counts['count'] / recent_counts['count'].sum() * 100
fig = px.pie(
recent_counts,
values='percentage',
names='Phase_of_Flight',
title='Proportion of Accidents by Phase of Flight (Last 10 Years)',
color_discrete_sequence=px.colors.sequential.Viridis
)
fig.show()
# 5. Monthly accident patterns (Line Chart)
df['Month'] = df['Event_Date'].dt.month
monthly_accidents = (
df.groupby(['Phase_of_Flight', 'Month'])
.size()
.reset_index(name='count')
)
plt.figure(figsize=(15, 8))
sns.lineplot(data=monthly_accidents, x='Month', y='count',
hue='Phase_of_Flight', marker='o')
plt.title('Monthly Accident Patterns by Phase of Flight')
plt.xlabel('Month')
plt.ylabel('Number of Accidents')
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
# 기본 통계 출력
summary_stats = (
phase_counts.groupby('Phase_of_Flight')
.agg({'count': ['mean', 'std', 'min', 'max']})
.round(2)
)
print("\n=== Summary Statistics for Accidents by Phase of Flight ===")
print(summary_stats)
분석 및 인사이트 도출
1. Total Accidents by Phase of Flight (Bar Chart)

- 해석: 대부분의 사고는
Landing
(착륙)과Takeoff
(이륙) 단계에서 발생했으며, 이는 항공 운항에서 가장 중요한 단계임을 나타냅니다. 상대적으로Other
,Unknown
, 및Standing
단계에서는 사고 빈도가 매우 낮습니다. - 인사이트:
- 착륙과 이륙 단계는 조종사와 관제사 간의 협업, 항공기의 성능, 기상 조건 등에 크게 의존하므로 안전 조치가 중요합니다.
Cruise
단계는 고도 유지와 안정된 상태이지만 사고 발생률이 세 번째로 높아 이 구간에서도 개선이 필요합니다.
2. Annual Accident Trends by Phase of Flight (Line Chart)

- 해석: 전체 사고는 시간이 지남에 따라 감소하는 추세를 보이고 있습니다. 특히
Cruise
와Landing
에서 사고 감소가 두드러집니다. - 인사이트:
- 항공기 기술의 발전, 강화된 규제, 훈련 프로그램의 개선이 주요 원인일 가능성이 큽니다.
- 특정 연도에 급증하는 사고는 해당 연도의 사건 또는 특정 기술적/환경적 요인과 관련될 수 있습니다.
3. Heatmap of Accidents by Year and Phase of Flight

- 해석: 착륙(
Landing
)과 이륙(Takeoff
) 단계에서 전 연도에 걸쳐 높은 사고 빈도가 관찰됩니다. 특정 연도의Approach
와Cruise
단계에서의 사고도 눈에 띕니다. - 인사이트:
- 착륙 및 이륙 단계는 지속적으로 고위험 구간으로 분류됩니다.
- 특정 연도에 집중된 패턴은 계절적, 지역적, 또는 운영상의 요인과 관련이 있을 수 있습니다.
4. Accident Proportion by Phase of Flight (Last 10 Years – Pie Chart)

- 해석: 최근 10년간 사고의 비율은
Landing
이 가장 높으며,Takeoff
와Cruise
가 뒤를 잇습니다. 나머지 단계에서는 상대적으로 낮은 비율을 보입니다. - 인사이트:
- 착륙 및 이륙 단계는 사고 예방 조치를 더욱 강화해야 할 필요성을 시사합니다.
Cruise
단계의 사고도 여전히 주목해야 하며, 기술적 문제(예: 엔진 고장)와 같은 원인을 분석해야 합니다.
5. Monthly Accident Patterns by Phase of Flight (Line Chart)

- 해석:
Landing
과Takeoff
단계에서 여름철(6월~8월)에 사고 건수가 증가하는 경향이 있습니다. 이는 여름철 항공기 운항 증가와 관련될 수 있습니다. - 인사이트:
- 여름철에 항공 운항량 증가로 인해 사고 발생 가능성이 높아집니다.
- 계절적 영향을 줄이기 위해 추가적인 유지보수와 훈련 프로그램을 강화해야 합니다.
6. Summary Statistics for Accidents by Phase of Flight

- 해석:
Landing
단계는 평균 사고 건수(593.38)가 가장 높고, 표준편차(129.93)도 크며, 최대값(472)으로 높은 변동성을 보입니다. - 인사이트:
- 착륙 단계에서 사고 건수가 다양하게 발생하며, 이는 조건(날씨, 조종사 숙련도 등)에 따라 크게 영향을 받음을 나타냅니다.
- 이륙(
Takeoff
)과 착륙 단계의 표준화된 절차 준수가 사고를 줄이는 데 중요합니다.
종합 인사이트
착륙과 이륙 단계 집중 개선
- 데이터는 착륙과 이륙 단계에서 사고가 집중적으로 발생한다는 것을 명확히 보여줍니다. 이를 해결하기 위해 조종사 훈련 강화와 항공기 상태 점검을 더욱 철저히 해야 합니다.
- 계절적 요인 분석 필요: 여름철 사고 증가를 고려하여 계절별 예방 조치를 강화해야 합니다.
- 기술적 향상 지속 필요:
Cruise
단계와 같은 장거리 운항 구간에서의 기술적 문제를 해결하기 위한 연구와 투자가 중요합니다. - 특정 연도/단계 데이터 심층 분석: 특정 연도에 집중된 사고를 분석하여 항공기 모델, 운영 절차, 외부 요인을 점검하는 것이 필요합니다.
파이썬 코드 상세해설
라이브러리 설치 및 임포트
!pip install kaggle -q # Kaggle 라이브러리 설치 import os import pandas as pd import seaborn as sns import matplotlib.pyplot as plt import plotly.express as px
이 섹션에서는 필요한 라이브러리를 설치하고 임포트합니다. Kaggle API를 사용하기 위해 kaggle 라이브러리를 설치하고, 데이터 분석 및 시각화를 위한 pandas, seaborn, matplotlib, plotly 라이브러리를 임포트합니다.
Kaggle API 설정
os.environ['KAGGLE_CONFIG_DIR'] = '/content' # 현재 디렉토리로 설정 !chmod 600 /content/kaggle.json # 권한 설정
Kaggle API를 사용하기 위해 환경 변수를 설정하고, API 키 파일(kaggle.json)의 권한을 설정합니다.
데이터 다운로드 및 로드
!kaggle datasets download -d khsamaha/aviation-accident-database-synopses -p /content/aviation_data --unzip file_path = "/content/aviation_data/AviationData.csv" df = pd.read_csv(file_path, encoding='ISO-8859-1', low_memory=False)
Kaggle API를 사용하여 데이터셋을 다운로드하고 압축을 해제합니다. 그 후 pandas를 사용하여 CSV 파일을 데이터프레임으로 로드합니다.
데이터 전처리
df.rename(columns={"Event Date": "Event_Date", "Broad.phase.of.flight": "Phase_of_Flight"}, inplace=True) df['Event_Date'] = pd.to_datetime(df['Event_Date'], errors='coerce') df['Year'] = df['Event_Date'].dt.year df = df.dropna(subset=['Phase_of_Flight'])
열 이름을 변경하고, 날짜 데이터를 datetime 형식으로 변환합니다. ‘Year’ 열을 추가하고, 결측치가 있는 행을 제거합니다.
데이터 집계
phase_counts = ( df.groupby(['Phase_of_Flight', 'Year']) .size() .reset_index(name='count') )
운항 단계와 연도별로 사고 건수를 집계합니다.
파이썬 시각화
- 운항 단계별 총 사고 건수 (막대 차트)
- 운항 단계별 연간 사고 추세 (선 그래프)
- 연도 및 운항 단계별 사고 히트맵
- 최근 10년간 운항 단계별 사고 비율 (인터랙티브 파이 차트)
- 월별 사고 패턴 (선 그래프)
각 시각화에 대해 적절한 그래프 유형을 선택하고, matplotlib, seaborn, plotly를 사용하여 구현합니다.
기본 통계 출력
summary_stats = ( phase_counts.groupby('Phase_of_Flight') .agg({'count': ['mean', 'std', 'min', 'max']}) .round(2) ) print("\n=== Summary Statistics for Accidents by Phase of Flight ===") print(summary_stats)
운항 단계별 사고 건수에 대한 기본 통계(평균, 표준편차, 최소값, 최대값)를 계산하고 출력합니다.
정리하기 – 제주항공 사고 애도와 경계
제주항공 사고는 정말 가슴이 아픈 항공 참사입니다. 전 국민이 애도해야 하는게 맞고, 그와 함께 원인분석과 대책도 철저히 해야 할 것입니다. 더불어, 이번 참사가 정치적으로 이용되지 않도록 우리 모두가 깨어있는 정신으로 살펴야 할 것 같습니다.
파이썬과 같은 도구를 활용하면 위험을 식별하고 생명을 구할 수 있는 솔루션을 구현하는데 인사이트를 얻을 수가 있습니다. 이번 비극을 애도하며, 더 안전한 하늘을 만들기 위해 온국민의 관심이 필요합니다. 이번 항공기 사고 데이터 분석은 그 여정을 위한 작은 발걸음이 되기를 바랍니다.