ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [2월 4주차-2/28]항공 데이터 분석: 지연 패턴과 인사이트 도출💦
    Why Not SW CAMP 5기/수업 기록 2025. 2. 28. 17:04

    데이터 로드 후 통합

    import pandas as pd
    import numpy as np
    
    cols_to_drop = [
        'DepTime',         # 실제 출발 시각 (예약 시각 사용)
        'ArrTime',         # 실제 도착 시각
        'CRSArrTime',      # 예약 도착 시각
        'FlightNum',       # 항공편 번호
        'CRSElapsedTime',  # 예약 운항 시간
        'AirTime',         # 실제 공중 비행 시간
        'TaxiIn',          # 착륙 후 택시 시간
        'TaxiOut',         # 이륙 전 택시 시간
        'CancellationCode',# 취소 사유 (분석 목적에 따라 생략)
        'Diverted',        # 우회 여부
        'NASDelay',        # 항공 관제 관련 지연
        'SecurityDelay'    # 보안 관련 지연
    ]
    
    flights = []
    for i in range(1987, 2009):
        df = pd.read_csv(f'data/{i}.csv', encoding="ISO-8859-1")  # 파일 읽기
        flights.append(df)
    
    # 하나의 데이터프레임으로 합치기
    flight_data = pd.concat(flights, ignore_index=True)
    
    flight_data = flight_data.drop(columns=cols_to_drop)
    
    airports_df = pd.read_csv("data/airports.csv")
    carriers_df = pd.read_csv("data/carriers.csv")
    plane_df = pd.read_csv("data/plane-data.csv")
    
    # 'year' 컬럼을 'PlaneYear'로 변경
    plane_df.rename(columns={'year': 'PlaneYear'}, inplace=True)
    
    # df_reduced의 항공기 등록번호 컬럼은 'TailNum'임. plane_df의 'tailnum'과 병합
    flight_data = pd.merge(flight_data, plane_df[['tailnum', 'PlaneYear']], how='left',
                          left_on='TailNum', right_on='tailnum')
    
    # 항공편 발생 연도(Year)와 제조 연도(PlaneYear)로 항공기 연식(AircraftAge) 계산
    flight_data['AircraftAge'] = flight_data['Year'] - flight_data['PlaneYear']
    
    # 불필요한 병합 후의 'tailnum' 컬럼 제거
    flight_data.drop(columns=['tailnum'], inplace=True)
    print("plane-data 병합 후 flight_data 컬럼:", flight_data.columns)
    
    # carriers 데이터와 병합하여 항공사명(Description) 추가 (carriers_df의 'Code' 기준)
    flight_data = pd.merge(flight_data, carriers_df, how='left',
                          left_on='UniqueCarrier', right_on='Code')

     

    지연을 최소화하려면 비행에 가장 적합한 시간대/요일/시간은 언제인가?

    #출발지연을 최소화하려면 비행에 가장 적합한 시간대/요일/시간은 언제인가?
    
    # 월 평균 출발 지연
    monthly_avg_delay = flight_data.groupby("Month")["DepDelay"].mean().reset_index()
    
    # 선 그래프 시각화
    plt.figure(figsize=(12, 6))
    sns.lineplot(data=monthly_avg_delay, x="Month", y="DepDelay", marker="o", color="b")
    plt.xlabel("Month")
    plt.ylabel("Average Departure Delay (minutes)")
    plt.title("Monthly Average Departure Delay (1995-2008)")
    plt.xticks(range(1, 13))
    plt.grid(True)
    plt.show()
    
    # 시간대 & 요일별 출발 지연 평균 계산
    flight_data["Hour"] = flight_data["CRSDepTime"] // 100  # 시간(HH만 추출)
    heatmap_data = flight_data.pivot_table(index="DayOfWeek", columns="Hour", values="DepDelay", aggfunc="mean")
    
    # 9월 데이터 필터링
    september_data = flight_data[flight_data["Month"] == 9]
    september_data["Hour"] = september_data["CRSDepTime"] // 100  # 시간(HH만 추출)
    heatmap_september = september_data.pivot_table(index="DayOfWeek", columns="Hour", values="DepDelay", aggfunc="mean")
    
    # 9월 히트맵 시각화
    plt.figure(figsize=(12, 6))
    sns.heatmap(heatmap_september, cmap="coolwarm", annot=True, linewidths=0.5)
    plt.xlabel("Hour of Day")
    plt.ylabel("Day of Week (1=Mon, 7=Sun)")
    plt.title("Average Departure Delay in September by Time and Day of Week")
    plt.show()
    
    # 12월 데이터 필터링
    december_data = flight_data[flight_data["Month"] == 12]
    december_data["Hour"] = december_data["CRSDepTime"] // 100  # 시간(HH만 추출)
    heatmap_december = december_data.pivot_table(index="DayOfWeek", columns="Hour", values="DepDelay", aggfunc="mean")
    
    # 12월 히트맵 시각화
    plt.figure(figsize=(12, 6))
    sns.heatmap(heatmap_december, cmap="coolwarm", annot=True, linewidths=0.5)
    plt.xlabel("Hour of Day")
    plt.ylabel("Day of Week (1=Mon, 7=Sun)")
    plt.title("Average Departure Delay in December by Time and Day of Week")
    plt.show()

    오래된 비행기일수록 지연이 더 잦나?

    # 오래된 비행기일수록 지연이 더 잦나?
    # 비행기 연식별 평균 도착 지연 시간 계산
    age_arrival_delay = flight_data.groupby("AircraftAge")["ArrDelay"].mean().reset_index()
    
    age_arrival_delay = age_arrival_delay[age_arrival_delay['AircraftAge'] >= 0]
    age_arrival_delay = age_arrival_delay[age_arrival_delay['AircraftAge'] < 60]
    
    # 그래프 설정
    sns.lineplot(x="AircraftAge", y="ArrDelay", data=age_arrival_delay, marker='o', color='r')
    plt.title("Average Arrival Delay by Aircraft Age")
    plt.xlabel("Aircraft Age (Years)")
    plt.ylabel("Average Arrival Delay (Minutes)")
    
    plt.tight_layout()
    plt.show()
    
    flight_data[['AircraftAge', 'ArrDelay']].corr()

    시간이 지나며 따라 다양한 장소 간을 비행하는 사람의 수는 어떻게 변하나?

    # 시간이 지남에 따라 다양한 장소 간을 비행하는 사람의 수는 어떻게 변하나?
    # 연도별 항공편 수 계산
    yearly_flights = flight_data.groupby("Year").size().reset_index(name="FlightCount")
    
    # 월별 항공편 수 계산
    monthly_flights = flight_data.groupby(["Year", "Month"]).size().reset_index(name="FlightCount")
    
    # 그래프 그리기
    plt.figure(figsize=(12, 5))
    
    # 연도별 항공편 수 트렌드
    plt.subplot(1, 2, 1)
    sns.lineplot(data=yearly_flights, x="Year", y="FlightCount", marker='o')
    plt.title("Total Flights per Year")
    plt.xlabel("Year")
    plt.ylabel("Number of Flights")
    
    # 월별 항공편 수 변화 트렌드
    plt.subplot(1, 2, 2)
    sns.lineplot(data=monthly_flights, x="Month", y="FlightCount", hue="Year", palette="coolwarm")
    plt.title("Monthly Flight Trends Over the Years")
    plt.xlabel("Month")
    plt.ylabel("Number of Flights")
    
    plt.tight_layout()
    plt.show()

    날씨는 비행기 지연을 얼마나 잘 예측할 수 있나?

    #날씨는 비행기 지연을 얼마나 잘 예측할 수 있나?
    
    flight_data["WeatherImpact_Dep"] = flight_data["WeatherDelay"] / flight_data["DepDelay"]
    flight_data["WeatherImpact_Arr"] = flight_data["WeatherDelay"] / flight_data["ArrDelay"]
    
    # 2. 상관관계 분석
    correlation = flight_data[["WeatherDelay", "DepDelay", "ArrDelay"]].corr()
    print("Correlation Matrix:\n", correlation)
    
    # 3. 월별 날씨 지연 패턴 분석
    monthly_weather_delay = flight_data.groupby("Month")["WeatherDelay"].mean()
    
    # 그래프 그리기
    plt.figure(figsize=(12, 5))
    
    # 월별 날씨 지연 평균
    plt.subplot(1, 2, 1)
    sns.lineplot(x=monthly_weather_delay.index, y=monthly_weather_delay.values, marker='o')
    plt.title("Average Weather Delay by Month")
    plt.xlabel("Month")
    plt.ylabel("Average Weather Delay (minutes)")
    
    # 히트맵으로 상관관계 시각화
    plt.subplot(1, 2, 2)
    sns.heatmap(correlation, annot=True, cmap="coolwarm", fmt=".2f")
    plt.title("Correlation between Weather Delay & Flight Delays")
    
    plt.tight_layout()
    plt.show()

    한 공항의 지연으로 인해 다른 공항의 지연이 발생하는 연쇄적 실패를 감지할 수 있는지?

    # 한 공항의 지연으로 인해 다른 공항의 지연이 발생하는 연쇄적 실패를 감지할 수 있는지? 
    
    import networkx as nx
    # 기존 데이터에서 평균 출발 및 도착 지연 계산
    delay_network = flight_data.groupby(["Origin", "Dest"])[["DepDelay", "ArrDelay"]].mean().reset_index()
    
    # 1. 평균 지연이 30분 이상인 공항만 필터링
    high_delay_routes = delay_network[(delay_network["DepDelay"] > 30) & (delay_network["ArrDelay"] > 30)]
    
    # 2. 그래프 생성
    G = nx.DiGraph()
    
    # 3. 필터링된 데이터 기반으로 노드 및 엣지 추가
    for _, row in high_delay_routes.iterrows():
        G.add_edge(row["Origin"], row["Dest"], weight=row["DepDelay"])
    
    # 4. Degree 기준으로 필터링 (연결된 공항이 5개 이상인 경우만)
    node_degree = dict(G.degree())
    filtered_nodes = [node for node, degree in node_degree.items() if degree >= 5]
    G_filtered = G.subgraph(filtered_nodes)
    
    # 5. 네트워크 그래프 시각화
    plt.figure(figsize=(12, 8))
    pos = nx.spring_layout(G_filtered, k=0.5)  # 노드 간격 조정
    
    # 노드 크기를 연결된 개수(degree)에 따라 가변적으로 설정
    node_sizes = [node_degree[node] * 200 for node in G_filtered.nodes()]
    
    nx.draw(G_filtered, pos, with_labels=True, node_size=node_sizes, font_size=10, edge_color="red")
    plt.title("Simplified Flight Delay Propagation Network")
    plt.show()

    9/11 이전과 이후의 비행 패턴을 비교.

    # 9/11 이전과 이후의 비행 패턴을 비교
    # 연도별 비행 횟수 계산
    flights_per_year = flight_data.groupby("Year").size()
    
    # 연도별 평균 지연 시간 계산
    average_delay_per_year = flight_data.groupby("Year")["ArrDelay"].mean()
    
    # 시각화 설정
    fig, ax1 = plt.subplots(figsize=(10,5))
    
    # 첫 번째 그래프 (비행 횟수 변화)
    color = 'tab:blue'
    ax1.set_xlabel('Year')
    ax1.set_ylabel('Number of Flights', color=color)
    ax1.plot(flights_per_year.index, flights_per_year.values, marker='o', color=color, label='Number of Flights')
    ax1.tick_params(axis='y', labelcolor=color)
    
    # 두 번째 그래프 (평균 지연 시간 변화)
    ax2 = ax1.twinx()  # Y축 공유
    color = 'tab:red'
    ax2.set_ylabel('Average Delay (minutes)', color=color)
    ax2.plot(average_delay_per_year.index, average_delay_per_year.values, marker='s', linestyle='--', color=color, label='Avg Delay Time')
    ax2.tick_params(axis='y', labelcolor=color)
    
    # 제목 및 범례 추가
    fig.suptitle('Yearly Flight Count and Average Delay Time')
    ax1.legend(loc='upper left')
    ax2.legend(loc='upper right')
    
    # 그래프 출력
    plt.show()

    가장 자주 비행하는 두 도시 간을 오가는 모든 항공편을 비교.

    #가장 자주 비행하는 두 도시 간을 오가는 모든 항공편을 비교.
    
    # 가장 자주 운항된 두 도시 찾기
    # 2007년 데이터 필터링
    flight_data_2007 = flight_data[flight_data["Year"] == 2007]
    
    # 가장 자주 운항된 두 도시 찾기
    route_counts = flight_data_2007.groupby(["Origin", "Dest"]).size().reset_index(name="count")
    top_route = route_counts.nlargest(1, "count")
    
    # 해당 구간의 데이터 필터링
    top_origin, top_dest = top_route.iloc[0]["Origin"], top_route.iloc[0]["Dest"]
    filtered_df = flight_data_2007[(flight_data_2007["Origin"] == top_origin) & (flight_data_2007["Dest"] == top_dest)]
    
    # 이상치 제거 (지연 시간이 180분 이하인 데이터만 사용)
    filtered_df = filtered_df[(filtered_df["DepDelay"].between(0, 120)) & (filtered_df["ArrDelay"].between(0, 120))]
    
    # 시각화 - 출발 및 도착 지연 비교
    plt.figure(figsize=(12, 6))
    sns.histplot(filtered_df["DepDelay"], bins=30, color="blue", label="Departure Delay", kde=True)
    sns.histplot(filtered_df["ArrDelay"], bins=30, color="orange", label="Arrival Delay", kde=True)
    plt.legend()
    plt.title(f"Flight Delay Distribution (2007): {top_origin} ↔ {top_dest}")
    plt.xlabel("Delay (minutes)")
    plt.ylabel("Count")
    plt.show()

    시카고(ORD)와 같은 주요 공항을 오가는 상위 5개의 항공편을 비교.

    ord_flights = flight_data[(flight_data["Origin"] == "ORD") | (flight_data["Dest"] == "ORD")]
    
    # ORD와 가장 많이 연결된 공항 찾기
    ord_routes = ord_flights.groupby(["Origin", "Dest"]).size().reset_index(name="count")
    top_ord_route = ord_routes.nlargest(5, "count")  # 가장 많은 항공편이 운항된 경로 5개 선택
    
    # 상위 5개 공항의 평균 출발 지연 & 도착 지연 비교
    top_5_airports = top_ord_route[["Origin", "Dest"]].values.flatten()
    filtered_top_5_df = ord_flights[(ord_flights["Origin"].isin(top_5_airports)) & 
                                    (ord_flights["Dest"].isin(top_5_airports))]
    
    delay_means = filtered_top_5_df.groupby(["Origin", "Dest"])[["DepDelay", "ArrDelay"]].mean().reset_index()
    
    plt.figure(figsize=(12, 6))
    sns.barplot(data=delay_means.melt(id_vars=["Origin", "Dest"], var_name="DelayType", value_name="Minutes"),
                x="Origin", y="Minutes", hue="DelayType", palette={"DepDelay": "blue", "ArrDelay": "orange"})
    
    plt.title("Average Departure & Arrival Delay for Top 5 Routes")
    plt.xlabel("Airport")
    plt.ylabel("Average Delay (minutes)")
    plt.legend(title="Delay Type")
    plt.grid(axis="y", linestyle="--", alpha=0.7)
    plt.show()
    
    
    # 상위 5개 공항의 시간대별 평균 지연 비교
    filtered_top_5_df["Hour"] = (filtered_top_5_df["CRSDepTime"] // 100).astype(int)  # 시간대 추출
    hourly_delay_top_5 = filtered_top_5_df.groupby(["Hour", "Origin"])[["DepDelay", "ArrDelay"]].mean().reset_index()
    
    plt.figure(figsize=(12, 6))
    sns.lineplot(data=hourly_delay_top_5, x="Hour", y="DepDelay", hue="Origin", marker="o", palette="tab10")
    plt.title("Average Departure Delay by Hour for Top 5 Airports")
    plt.xlabel("Hour of the Day")
    plt.ylabel("Average Departure Delay (minutes)")
    plt.xticks(range(0, 24))
    plt.legend(title="Airport")
    plt.grid(True)
    plt.show()

    항공사별 평균 출발 지연 시간을 비교하여 어떤 항공사가 가장 정시 운항을 잘하는지 분석

    import pandas as pd
    import matplotlib.pyplot as plt
    import seaborn as sns
    # 운영체제에 맞는 기본 폰트 설정
    from matplotlib import font_manager, rc
    import platform
    
    if platform.system() == 'Darwin':
        rc('font', family = 'AppleGothic')
    elif platform.system() == 'Windows':
        path = 'c:/Windows/Fonts/malgun.ttf'
        font_name = font_manager.FontProperties(fname=path).get_name()
        rc('font', family=font_name)
    else:
        print("sorry")
    
    # 새로운 데이터프레임 생성 (원본 유지)
    df_analysis = flight_data[['UniqueCarrier', 'DepDelay']].copy()
    
    # 결측값 제거
    df_analysis = df_analysis.dropna()
    
    # 항공사별 평균 출발 지연 시간 계산
    carrier_delay = df_analysis.groupby('UniqueCarrier')['DepDelay'].mean().reset_index()
    
    # 평균 출발 지연 시간이 낮은 순으로 정렬
    carrier_delay = carrier_delay.sort_values(by='DepDelay')
    
    # 시각화 (막대 그래프)
    plt.figure(figsize=(12, 6))
    sns.barplot(x='UniqueCarrier', y='DepDelay', data=carrier_delay, palette='coolwarm')
    plt.xlabel('항공사 코드')
    plt.ylabel('평균 출발 지연 시간 (분)')
    plt.title('항공사별 평균 출발 지연 시간 비교')
    plt.xticks(rotation=45)
    plt.show()
    
    # 가장 정시 운항을 잘하는 항공사 출력
    best_carrier = carrier_delay.iloc[0]
    print(f'가장 정시 운항을 잘하는 항공사: {best_carrier["UniqueCarrier"]}, 평균 출발 지연 시간: {best_carrier["DepDelay"]:.2f}분')
    
    # 가장 출발 지연이 심한 항공사 출력
    worst_carrier = carrier_delay.iloc[-1]
    print(f'가장 출발 지연이 심한 항공사: {worst_carrier["UniqueCarrier"]}, 평균 출발 지연 시간: {worst_carrier["DepDelay"]:.2f}분')

     

Designed by Tistory.