본문 바로가기
파이썬 코딩/논문 그림 따라하기

Python 논문 시각화 실전 가이드: Matplotlib 다중 시계열 그래프로 허리케인 강도 변화 그래프 그리기

by 광원다이노스 2025. 5. 11.

2025.05.11 - [파이썬 코딩/논문 그림 따라하기] - Python 논문 시각화 실전 가이드: 히트맵(heatmap)으로 허리케인 해상 분무 효과 나타내기

 

Python 논문 시각화 실전 가이드: 히트맵(heatmap)으로 허리케인 해상 분무 효과 나타내기

서론2024년 ERL에 게재한 논문 "Unveiling the pivotal influence of sea spray heat fluxes on hurricane rapid intensification"에서 소개한 Figure 1의 Python 코드를 상세히 설명하려 한다. 이 그림은 해상 분무(sea spray)가 허리

special-waddle.tistory.com

2025.05.11 - [파이썬 코딩/논문 그림 따라하기] - Python 논문 시각화 실전 가이드: Matplotlib을 활용한 허리케인 단면도 그리기

 

Python 논문 시각화 실전 가이드: Matplotlib을 활용한 허리케인 단면도 그리기

2025.05.11 - [파이썬 코딩/논문 그림 따라하기] - 허리케인 급 강화와 해상 분무의 중요성 연구(Figure 1, YK24) 서론지난 포스팅에 이어서 "Unveiling the pivotal influence of sea spray heat fluxes on hurricane rapid inten

special-waddle.tistory.com

 

서론

지난 포스팅에 이어서, 이번 포스팅에서는 논문 "Unveiling the pivotal influence of sea spray heat fluxes on hurricane rapid intensification"의 Figure 3을 생성하는 코드를 살펴보려 한다. 이 그림은 여러 허리케인 사례에 대해 시간에 따른 강도 변화를 보여주는 핵심 시계열 그래프이다.

 

배경

허리케인의 강도는 주로 두 가지 핵심 지표로 측정된다:

  1. 최저 해면 기압(Pmin): 값이 낮을수록 강한 허리케인
  2. 최대 지상 풍속(Vmax): 값이 높을수록 강한 허리케인

이 그림에서는 4개의 주요 허리케인 사례(Ida 2021, Ian 2022, Michael 2018, Harvey 2017)에 대한 3가지 시뮬레이션 결과를 미국 국립 허리케인 센터(NHC)의 관측 자료(best track data)와 비교했다:

  1. UNCPL: 대기 모델만 사용한 결합되지 않은 시뮬레이션
  2. CPL: 대기-해양 결합 시뮬레이션 (해상 분무 효과 없음)
  3. SPRAY: 대기-해양-파랑 결합 시뮬레이션 (해상 분무 효과 포함)

이를 통해 해상 분무가 허리케인의 강도 예측과 급격한 강화에 미치는 영향을 정량적으로 평가할 수 있다.

 

1. 필요한 라이브러리 불러오기 및 기본 설정

import numpy as np
import xarray as xr
import pandas as pd
import matplotlib.pyplot as plt

labels = ['UNCPL', 'CPL', 'SPRAY']
colors = ['k', 'k', 'red']
styles = ['--', '-', '-']
widths = [ 1, 2, 2]

kt2ms = 0.514444  # 노트에서 미터/초로의 변환 계수

titles = [ 'Ida (2021)', 'Ian (2022)', 'Michael (2018)', 'Harvey (2017)' ]
date_ranges = [ pd.date_range('2021-08-27 00:00:00', '2021-08-30 00:00:00', freq='6h'),
                pd.date_range('2022-09-26 00:00:00', '2022-09-29 00:00:00', freq='6h'),
                pd.date_range('2018-10-08 00:00:00', '2018-10-11 00:00:00', freq='6h'),
                pd.date_range('2017-08-24 00:00:00', '2017-08-27 00:00:00', freq='6h') ]

여기서는:

  1. 데이터 처리를 위한 numpy와 pandas, 시각화를 위한 matplotlib을 불러온다.
  2. 각 시뮬레이션 설정에 대한 라벨, 색상, 선 스타일, 선 두께를 정의한다.
  3. 노트(kt)에서 미터/초(m/s)로 풍속 단위를 변환하기 위한 계수를 설정한다.
  4. 허리케인 사례 이름과 각 사례의 분석 기간(72시간)을 정의한다.

 

2. 데이터 로드 및 시각화 설정

df = pd.read_csv("ERL_P1_Fig_03__ts_Pmin_Vmax_combined_df.csv", index_col='date', parse_dates=True)

xlabel = 'Forecast Period [h]'
ylabel_list = [r'P$_{min}$ [hPa]', r'V$_{max}$ [m s$^{-1}$]']

fig, axs = plt.subplots(len(ylabel_list), len(titles), figsize=(9,4),
        constrained_layout=True, sharex=True, sharey=False)

이 부분에서는:

  1. CSV 파일에서 허리케인 강도 데이터를 pandas 데이터프레임으로 불러온다. 이때 날짜 칼럼을 인덱스로 설정하고 날짜 형식으로 파싱한다.
  2. x축과 y축 레이블을 정의한다.
  3. 2×4 서브플롯 구조를 생성한다: 2개 행(Pmin과 Vmax)과 4개 열(허리케인 사례).

 

3. 시계열 그래프 생성

for col, (date_range, title) in enumerate(zip(date_ranges, titles)):
    # NHC 관측 데이터 그리기
    of = df[(df['name']==title)&(df['source'] == 'NHC')].loc[date_range[0]:date_range[-1]]
    x = np.arange(len(of.index))
    axs[0, col].plot(x, of.mslp, lw=2, color='grey', label='NHC')
    axs[1, col].plot(x, of.vmax*kt2ms, lw=2, color='grey', label='NHC')
    
    # 모델 결과 그리기
    for label, color, ls, lw in zip(labels, colors, styles, widths):
        mf = df[(df['name']==title)&(df['source'] == label)].loc[date_range[0]:date_range[-1]]
        axs[0, col].plot(x, mf['mslp'], lw=lw, ls=ls, color=color, label=label,)
        axs[1, col].plot(x, mf['vmax']*kt2ms, lw=lw, ls=ls, color=color, label=label,)
    
    # 제목 및 축 범위 설정
    axs[0, col].set_title(title, fontsize=15)
    axs[0, col].set_ylim([915, 1010])
    axs[1, col].set_ylim([17/2, 143/2])
    
    # 첫 번째 열을 제외한 나머지 열의 y축 눈금 레이블 제거
    if col > 0:
        axs[0, col].set_yticklabels("")
        axs[1, col].set_yticklabels("")

이 부분은 코드의 핵심으로, 각 허리케인 사례에 대한 시계열 그래프를 생성한다:

  1. 먼저 각 사례에 대한 NHC 관측 데이터를 회색 선으로 그린다.
  2. 세 가지 모델 설정(UNCPL, CPL, SPRAY)의 결과를 서로 다른 선 스타일과 색상으로 그린다.
  3. 각 서브플롯에 제목을 추가하고, y축 범위를 설정한다.
  4. 첫 번째 열을 제외한 나머지 열의 y축 눈금 레이블을 제거하여 시각적 중복을 피한다.

 

4. 레이아웃 스타일 조정

for i, ax in enumerate(axs.flatten()):
    ax.grid(ls=":")
    ax.set_xticks(x[::2])
    ax.set_xticklabels(x[::2]*6)
    ax.legend(loc='best', frameon=False, prop={'size': 8})
    if i >= 4:  # 아래 행에만 x축 레이블 추가
        ax.set_xlabel(xlabel, fontsize=11)

axs[0,0].set_ylabel(ylabel_list[0], fontsize=12)
axs[1,0].set_ylabel(ylabel_list[1], fontsize=12)

plt.show()
fig.savefig('fig_03__ts_tc_intensity_total.png', dpi=500, bbox_inches='tight')

이 부분에서는 그림의 최종 모양을 세밀하게 조정한다:

  1. 각 서브플롯에 점선 격자를 추가한다.
  2. x축 눈금을 설정하고, 눈금 레이블을 시간(시간)으로 변환한다. 6시간 간격으로 표시된다.
  3. 범례를 추가하고, 테두리 없이 최적의 위치에 배치한다.
  4. 하단 행에만 x축 레이블을 추가한다.
  5. 첫 번째 열에 y축 레이블을 추가한다.
  6. 고해상도(500dpi)로 그림을 저장한다.

 

코드 구현의 핵심 포인트

이 시각화 코드의 몇 가지 핵심 기법을 정리하면 다음과 같다:

  1. 다중 시계열 비교: 여러 시뮬레이션 결과를 동일한 그래프에 표시하여 직접 비교할 수 있게 했다.
  2. 통합된 데이터 처리: 모든 허리케인 사례와 모델 결과를 하나의 데이터프레임에 통합하여 효율적으로 처리했다.
  3. 날짜 인덱싱: pandas의 날짜 처리 기능을 활용하여 시간 범위를 쉽게 선택하고 처리했다.
  4. 일관된 시각화 스타일: 모델 설정별로 일관된 색상과 선 스타일을 사용하여 가독성을 높였다.

 

그림 해석

위 코드를 통해 생성된 Figure 3은 허리케인 강도에 해상 분무가 미치는 영향을 시간에 따라 명확하게 보여준다.

주요 발견점은 다음과 같다:

  1. 급 강화 재현: 해상 분무를 포함한 SPRAY(빨간색 실선)은 모든 허리케인 사례에서 관측된 강도를 가장 잘 재현한다. 특히 Ida와 Ian 사례에서 그 차이가 두드러진다.
  2. 해양 결합 효과: CPL은 UNCPL보다 허리케인이 약하게 나타난다. 이는 해양-대기 상호작용으로 인한 해수면 냉각 효과 때문이다.
  3. 해상 분무의 보상 효과: SPRAY은 해양 결합으로 인한 약화 효과를 상쇄하고도 남을 만큼 허리케인을 강화시킨다. 이는 해상 분무가 제공하는 추가적인 열 플럭스가 중요한 역할을 함을 보여준다.
  4. 사례별 차이: Harvey 사례에서는 모델 간 차이가 상대적으로 작은데, 이는 초기 강도가 약했기 때문이다. 강한 바람이 있어야 해상 분무가 충분히 생성되므로, 약한 시스템에서는 해상 분무의 효과가 제한적이다.

 

결론

이번 포스팅에서는 허리케인 강도의 시계열 변화를 시각화하는 Python 코드를 살펴보았다. 이 시각화를 통해 해상 분무가 허리케인의 급격한 강화에 매우 중요한 역할을 한다는 것을 명확하게 확인할 수 있었다. 특히, 해양-대기 결합 모델에서 해상 분무를 포함하면 관측된 급격한 강화를 훨씬 더 잘 재현할 수 있었다.

이러한 발견은 허리케인 예측 모델을 개선하는 데 큰 도움이 될 수 있다. 해상 분무 과정을 정교하게 표현하는 모델은 허리케인의 급격한 강화를 더 잘 예측할 수 있을 것으로 기대한다.

코드나 허리케인 모델링에 대한 질문이 있다면 댓글을 달아주세요!