earth :: 전세계의 바람, 날씨, 바다 상태를 보는 지도
earth :: 전세계의 바람, 날씨, 바다 상태를 보는 지도
슈퍼컴퓨터로 예보하는 현재의 바람, 날씨, 해양 및 오염 상황을 확인하세요. 인터랙티브 애니메이션 맵은 세 시간 간격으로 업데이트됩니다.
earth.nullschool.net

#1. 엘니뇨와 라니냐 시기에 해수면 수온 편차에 대해 조사를 실시


#2. 엘니뇨와 라니냐 시기에 무역풍 세기에 대해 조사를 실시


이 외 강수량, 기압 편차 등을 비교해 볼 수 있지 않을까
<과제> 엘니뇨와 라니냐 시기를 시각화할 수 있는 그래프 그리기
1. 데이터 수집하기
- 이 그래프를 그리기 위해서는 Nino 3.4 지역의 수온 데이터가 필요하다.
- 이를 제공하는 사이트에 접속하여 데이터를 확보한다. https://psl.noaa.gov/enso/data.html
https://psl.noaa.gov/enso/data.html
Datasets Useful for ENSO Research Sea Surface Temperature (SST) Gridded SST datasets are available for monthly means and for daily. Values can be mean or anomalies. Gaps usually exist in SST dataets both in space and time. Different datasets use different
psl.noaa.gov
- 위 사이트에서 Nino 3.4를 클릭 후, Time-series List 에서 csv 파일을 다운로드 한다.
- 데이터가 어떻게 구성되어있는지를 파악해야 코딩을 할 수 있으므로 자료를 열어 확인한다.
2. 구글 코랩에 접속하고 데이터 파일 업로드 하기
3. 생성형 AI를 활용하여 그래프를 그리기 위한 질문을 진행하기 + 코랩에서 코드 실행하기(반복)
- 가로축과 세로축에 어떠한 값이 설정되어 있는지 파악하기
- 데이터 자료가 원하는 결과 값을 포함하고 있지 않으면 코딩에서 가공하거나 본 데이터 csv 파일에서 열을 추가해야한다.
1) 첫번째 질문
| 날짜와 니노 3.4 지역의 csv 수온 자료가 있어. 이를 플롯팅할 수 있게 파이썬 코드를 작성해줘. |
import pandas as pd
import matplotlib.pyplot as plt
# CSV 파일 불러오기 (파일명을 알맞게 수정하세요)
# 예: 'nino34_data.csv'
df = pd.read_csv('nino34_data.csv')
# 날짜를 datetime 형식으로 변환 (열 이름이 'date'라고 가정)
df['date'] = pd.to_datetime(df['date'])
# 수온 열 이름이 'sst'라고 가정 (수정 가능)
plt.figure(figsize=(12, 6))
plt.plot(df['date'], df['sst'], label='Niño 3.4 SST', color='tomato')
# 제목 및 축 레이블 설정
plt.title('Niño 3.4 Sea Surface Temperature Over Time')
plt.xlabel('Date')
plt.ylabel('Sea Surface Temperature (°C)')
plt.grid(True)
plt.legend()
plt.tight_layout()
plt.show()

2) 두번째 질문
| csv 파일에 date와 sst (관측 수온) 자료만 있어. 수온 편차를 구하고, 이를 통해 엘니뇨 시기를 빨간색, 라니냐 시기를 파란색으로 색칠하고 싶어. |
import pandas as pd
import matplotlib.pyplot as plt
# 1. 데이터 불러오기 및 날짜 변환
df = pd.read_csv('nino34_data.csv')
df['date'] = pd.to_datetime(df['date'])
df['month'] = df['date'].dt.month
# 2. 월별 평균(기후 기준값) 계산
monthly_avg = df.groupby('month')['sst'].mean()
df['climatology'] = df['month'].map(monthly_avg)
# 3. 수온 편차 계산
df['anomaly'] = df['sst'] - df['climatology']
# 4. 그래프 시각화
plt.figure(figsize=(14, 6))
plt.plot(df['date'], df['anomaly'], color='black', label='SST Anomaly')
# 5. 엘니뇨 영역 색칠 (편차 ≥ +0.5°C)
plt.fill_between(df['date'], df['anomaly'], 0,
where=(df['anomaly'] >= 0.5),
color='red', alpha=0.4, label='El Niño (≥ +0.5°C)')
# 6. 라니냐 영역 색칠 (편차 ≤ -0.5°C)
plt.fill_between(df['date'], df['anomaly'], 0,
where=(df['anomaly'] <= -0.5),
color='blue', alpha=0.4, label='La Niña (≤ -0.5°C)')
# 7. 그래프 꾸미기
plt.axhline(0, color='gray', linestyle='--')
plt.title('Niño 3.4 SST Anomalies with El Niño / La Niña Periods')
plt.xlabel('Date')
plt.ylabel('SST Anomaly (°C)')
plt.grid(True)
plt.legend()
plt.tight_layout()
plt.show()

3) 세번째 질문
| 수온 편차가 0.5이상 차이가 나야 엘니뇨잖아. 근데 0보다 큰 + 영역에 엘니뇨(빨간색)으로 표시되어 있어. 그리고 3개월 이상 지속된 진짜 엘니뇨/라니냐 기간만 강조하고 싶어. 그리고 너무 옛날부터 자료가 있는데 1950년로부터로 기간을 축소시키고 싶어. |
import pandas as pd
import matplotlib.pyplot as plt
# 1. 데이터 불러오기 및 날짜 처리
df = pd.read_csv('nino34_data.csv')
df['date'] = pd.to_datetime(df['date'])
# 2. ⏳1950년 이후 자료만 선택
df = df[df['date'] >= '1950-01-01'].reset_index(drop=True)
# 3. 월별 평균 → 편차 계산
df['month'] = df['date'].dt.month
monthly_avg = df.groupby('month')['sst'].mean()
df['anomaly'] = df['sst'] - df['month'].map(monthly_avg)
# 4. 연속된 엘니뇨/라니냐 구간 판별 함수
def extract_persistent_periods(mask, min_length=3):
periods = []
in_period = False
start = None
for i in range(len(mask)):
if mask[i] and not in_period:
in_period = True
start = i
elif not mask[i] and in_period:
if i - start >= min_length:
periods.append((start, i))
in_period = False
if in_period and len(mask) - start >= min_length:
periods.append((start, len(mask)))
return periods
elnino_mask = df['anomaly'] >= 0.5
lanina_mask = df['anomaly'] <= -0.5
elnino_periods = extract_persistent_periods(elnino_mask.values)
lanina_periods = extract_persistent_periods(lanina_mask.values)
# 5. 그래프 시각화
plt.figure(figsize=(14, 6))
plt.plot(df['date'], df['anomaly'], color='black', label='SST Anomaly')
for start, end in elnino_periods:
plt.fill_between(df['date'][start:end], df['anomaly'][start:end], 0,
color='red', alpha=0.4, label='El Niño' if start == elnino_periods[0][0] else "")
for start, end in lanina_periods:
plt.fill_between(df['date'][start:end], df['anomaly'][start:end], 0,
color='blue', alpha=0.4, label='La Niña' if start == lanina_periods[0][0] else "")
plt.axhline(0, color='gray', linestyle='--')
plt.title('Significant Niño 3.4 SST Anomalies (Since 1950, ≥3 months)')
plt.xlabel('Date')
plt.ylabel('SST Anomaly (°C)')
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()

4) 네번째 질문
| 근데 여기서 0보다 큰 영역에 엘니뇨를 색깔로 칠했잖아. 0.5도 이상 편차가 나는 곳에만 색칠하게 못바꿔? 라니냐도 마찬가지로. |
import pandas as pd
import matplotlib.pyplot as plt
# 1. CSV 데이터 불러오기
df = pd.read_csv('nino34_data.csv') # 파일명은 실제에 맞게 수정
df['date'] = pd.to_datetime(df['date'])
# 2. 1950년 이후 데이터만 사용
df = df[df['date'] >= '1950-01-01'].reset_index(drop=True)
# 3. 월별 평균 수온 계산 (Climatology) 및 편차 계산
df['month'] = df['date'].dt.month
monthly_avg = df.groupby('month')['sst'].mean()
df['anomaly'] = df['sst'] - df['month'].map(monthly_avg)
# 4. 연속 조건 충족 여부 판단 함수 (3개월 이상)
def extract_persistent_periods(mask, min_length=3):
periods = []
in_period = False
start = None
for i in range(len(mask)):
if mask[i] and not in_period:
in_period = True
start = i
elif not mask[i] and in_period:
if i - start >= min_length:
periods.append((start, i))
in_period = False
if in_period and len(mask) - start >= min_length:
periods.append((start, len(mask)))
return periods
# 5. 엘니뇨 / 라니냐 구간 마스크 생성
elnino_mask = df['anomaly'] >= 0.5
lanina_mask = df['anomaly'] <= -0.5
elnino_periods = extract_persistent_periods(elnino_mask.values)
lanina_periods = extract_persistent_periods(lanina_mask.values)
# 6. 시각화
plt.figure(figsize=(14, 6))
plt.plot(df['date'], df['anomaly'], color='black', label='SST Anomaly')
# 7. 엘니뇨 색칠 (0.5도 이상만)
for i, (start, end) in enumerate(elnino_periods):
plt.fill_between(df['date'][start:end], df['anomaly'][start:end], 0.5,
where=(df['anomaly'][start:end] >= 0.5),
color='red', alpha=0.4,
label='El Niño' if i == 0 else "")
# 8. 라니냐 색칠 (-0.5도 이하만)
for i, (start, end) in enumerate(lanina_periods):
plt.fill_between(df['date'][start:end], df['anomaly'][start:end], -0.5,
where=(df['anomaly'][start:end] <= -0.5),
color='blue', alpha=0.4,
label='La Niña' if i == 0 else "")
# 9. 기준선과 꾸미기
plt.axhline(0, color='gray', linestyle='--')
plt.axhline(0.5, color='red', linestyle=':', linewidth=1)
plt.axhline(-0.5, color='blue', linestyle=':', linewidth=1)
plt.title('Significant Niño 3.4 SST Anomalies (Since 1950, ≥3 months)')
plt.xlabel('Date')
plt.ylabel('SST Anomaly (°C)')
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()

5) 마지막 질문
| 각 엘니뇨, 라니냐 시기에 피크점이 몇월 며칠인지 (예를 들어 17년 6월 1일이면 17.06.01) 표시 될까? 3개월 이상 연속된 엘니뇨가 아니고 5개월 이상 지속되는 경우로 바꿔줘. 라니냐도 마찬가지로. |
import pandas as pd
import matplotlib.pyplot as plt
# 1. 데이터 불러오기
df = pd.read_csv('nino34_data.csv')
df['date'] = pd.to_datetime(df['date'])
# 2. 1950년 이후로 필터링
df = df[df['date'] >= '1950-01-01'].reset_index(drop=True)
# 3. 월별 평균 수온으로 편차 계산
df['month'] = df['date'].dt.month
monthly_avg = df.groupby('month')['sst'].mean()
df['anomaly'] = df['sst'] - df['month'].map(monthly_avg)
# 4. 연속 구간 추출 함수 (min_length=5)
def extract_persistent_periods(mask, min_length=5):
periods = []
in_period = False
start = None
for i in range(len(mask)):
if mask[i] and not in_period:
in_period = True
start = i
elif not mask[i] and in_period:
if i - start >= min_length:
periods.append((start, i))
in_period = False
if in_period and len(mask) - start >= min_length:
periods.append((start, len(mask)))
return periods
# 5. 엘니뇨 / 라니냐 조건 마스크 및 구간 찾기
elnino_mask = df['anomaly'] >= 0.5
lanina_mask = df['anomaly'] <= -0.5
elnino_periods = extract_persistent_periods(elnino_mask.values, min_length=5)
lanina_periods = extract_persistent_periods(lanina_mask.values, min_length=5)
# 6. 시각화 준비
plt.figure(figsize=(14, 6))
plt.plot(df['date'], df['anomaly'], color='black', label='SST Anomaly')
# 7. 엘니뇨 색칠 (0.5도 이상만)
for i, (start, end) in enumerate(elnino_periods):
plt.fill_between(df['date'][start:end], df['anomaly'][start:end], 0.5,
where=(df['anomaly'][start:end] >= 0.5),
color='red', alpha=0.4,
label='El Niño (≥5 months)' if i == 0 else "")
# 8. 라니냐 색칠 (-0.5도 이하만)
for i, (start, end) in enumerate(lanina_periods):
plt.fill_between(df['date'][start:end], df['anomaly'][start:end], -0.5,
where=(df['anomaly'][start:end] <= -0.5),
color='blue', alpha=0.4,
label='La Niña (≥5 months)' if i == 0 else "")
# 9. 피크 날짜 주석 표시
def annotate_peaks(periods, color, peak_type='max'):
for start, end in periods:
segment = df.iloc[start:end]
if peak_type == 'max':
peak_idx = segment['anomaly'].idxmax()
else:
peak_idx = segment['anomaly'].idxmin()
peak_date = df.loc[peak_idx, 'date']
peak_value = df.loc[peak_idx, 'anomaly']
date_str = peak_date.strftime('%y.%m.%d')
plt.annotate(date_str,
xy=(peak_date, peak_value),
xytext=(0, 10),
textcoords='offset points',
ha='center', fontsize=8,
color=color,
arrowprops=dict(arrowstyle='->', color=color, lw=0.8))
annotate_peaks(elnino_periods, 'red', peak_type='max')
annotate_peaks(lanina_periods, 'blue', peak_type='min')
# 10. 기준선 및 마무리
plt.axhline(0, color='gray', linestyle='--')
plt.axhline(0.5, color='red', linestyle=':', linewidth=1)
plt.axhline(-0.5, color='blue', linestyle=':', linewidth=1)
plt.title('Niño 3.4 SST Anomalies (Since 1950, ≥5 months El Niño / La Niña)')
plt.xlabel('Date')
plt.ylabel('SST Anomaly (°C)')
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()

'지구과학도의 몸부림 > 수업' 카테고리의 다른 글
| [지구과학 Python] 행성 간 탐사(호먼궤도) (0) | 2025.09.11 |
|---|---|
| [지구과학 Python] 엘니뇨 라니냐 -② 엘니뇨, 라니냐 지구 구면에 시각화 (0) | 2025.06.16 |
| [천문학] 균시차 곡선 뿌시기 (0) | 2024.03.25 |
| [지구과학수행평가 참고 사이트] 미국해양대기청(NOAA) 데이터 시각화 (0) | 2024.03.25 |
| 지구 외적 기후변화 요인 (Feat. 지구과학 시뮬레이션 웹 사이트 소개 (Science Pickle)) (0) | 2023.06.17 |