제주도 여행하기 좋은 달, 데이터로 알아보는 최적의 시기! (feat. 파이썬)
안녕하세요, 여행 좋아하시는 여러분! 제주도 여행 계획 중이신가요? 아, 그 설레는 마음, 저도 너무 잘 알아요. 그런데 제주도 여행하기 좋은 달이 언제인지 고민되시죠? 날씨가 안 좋으면 여행이 망쳐질까 걱정되시는 분들, 주목해주세요! 오늘은 데이터로 알아보는 제주도 여행 최적의 시기, 함께 살펴볼게요.
제주도 여행하기 좋은 달, 언제가 좋을까?
제주도 여행하기 좋은 달을 찾는 건 정말 중요해요. 왜냐고요? 날씨가 여행의 질을 좌우하니까요! 그래서 저는 최근 1년간의 제주도 날씨 데이터를 분석해봤어요. 기온, 풍속, 구름량까지 꼼꼼히 살펴봤답니다.
일반적으로 여행하기 좋은 기후 조건은 다음과 같다고 합니다. 아래 조건에 맞는 달(month)을 한번 데이터를 분석해서 찾아보도록 하겠습니다.
- 평균 기온이 20°C에서 28°C 사이.
- 최대 풍속이 15km/h 미만.
- 평균 구름량이 50% 미만.
데이터로 보는 제주도 여행 최적기
자, 이제 파이썬의 마법을 부려볼 시간이에요! 제주도 여행하기 좋은 달을 찾기 위해 다음과 같은 코드를 작성했습니다. 여기서 참고로 WeatherAPI.com API를 이용해서 데이터를 불러왔는데요. 회원가입 후 Dashboard에서 API Key를 확인할 수 있습니다.
import requests
import pandas as pd
import matplotlib.pyplot as plt
from datetime import datetime, timedelta
from time import sleep
# WeatherAPI.com API key (replace with your actual key)
api_key = 'YOUR_API_KEY'
# List to store weather data
full_weather_data = []
# Collect data for the last year
end_date = datetime.now()
start_date = end_date - timedelta(days=365)
# Iterate over date range
for date in pd.date_range(start=start_date, end=end_date):
url = f"http://api.weatherapi.com/v1/history.json?key={api_key}&q=Jeju&dt={date.strftime('%Y-%m-%d')}"
try:
response = requests.get(url)
if response.status_code == 200:
data = response.json()
forecast_day = data['forecast']['forecastday'][0]['day']
# Add weather data
full_weather_data.append({
'date': date.strftime('%Y-%m-%d'),
'temp': forecast_day['avgtemp_c'],
'wind_speed': forecast_day['maxwind_kph'],
'cloud_cover': forecast_day['avghumidity']
})
print(f"Data for {date.strftime('%Y-%m-%d')} successfully added")
else:
print(f"Failed to fetch data for {date.strftime('%Y-%m-%d')}. Status code: {response.status_code}")
except Exception as e:
print(f"Error occurred while requesting data for {date.strftime('%Y-%m-%d')}: {e}")
# Wait time to consider API request limits
sleep(1)
# Create DataFrame
df = pd.DataFrame(full_weather_data)
df['date'] = pd.to_datetime(df['date'])
# Define good weather conditions
df['good_weather'] = (df['temp'].between(20, 28) &
(df['wind_speed'] < 15) &
(df['cloud_cover'] < 50))
# Calculate monthly averages and good weather days
monthly_data = df.groupby(df['date'].dt.to_period('M')).agg({
'temp': 'mean',
'wind_speed': 'mean',
'cloud_cover': 'mean',
'good_weather': 'sum'
}).reset_index()
monthly_data['date'] = monthly_data['date'].dt.to_timestamp()
# Visualization
plt.figure(figsize=(15, 12))
# Highlight best months for travel
best_months = monthly_data[monthly_data['good_weather'] > 0]
# Temperature plot
plt.subplot(3, 1, 1)
plt.plot(monthly_data['date'], monthly_data['temp'], marker='o')
plt.title('Monthly Average Temperature')
plt.ylabel('Temperature (°C)')
plt.axhline(y=20, color='r', linestyle='--', label='Lower Bound (20°C)')
plt.axhline(y=28, color='r', linestyle='--', label='Upper Bound (28°C)')
for idx, row in best_months.iterrows():
plt.annotate(row['date'].strftime('%b'), (row['date'], row['temp']),
textcoords="offset points", xytext=(0,10), ha='center',
fontsize=10, color='green')
# Wind speed plot
plt.subplot(3, 1, 2)
plt.plot(monthly_data['date'], monthly_data['wind_speed'], marker='o', color='green')
plt.title('Monthly Average Wind Speed')
plt.ylabel('Wind Speed (km/h)')
plt.axhline(y=15, color='r', linestyle='--', label='Wind Speed Threshold (15 km/h)')
for idx, row in best_months.iterrows():
plt.annotate(row['date'].strftime('%b'), (row['date'], row['wind_speed']),
textcoords="offset points", xytext=(0,10), ha='center',
fontsize=10, color='green')
# Cloud cover plot
plt.subplot(3, 1, 3)
plt.plot(monthly_data['date'], monthly_data['cloud_cover'], marker='o', color='blue')
plt.title('Monthly Average Cloud Cover')
plt.ylabel('Cloud Cover (%)')
plt.axhline(y=50, color='r', linestyle='--', label='Cloud Cover Threshold (50%)')
for idx, row in best_months.iterrows():
plt.annotate(row['date'].strftime('%b'), (row['date'], row['cloud_cover']),
textcoords="offset points", xytext=(0,10), ha='center',
fontsize=10, color='green')
plt.tight_layout()
# Final plot with legends and display
plt.legend(loc='upper right')
plt.show()
# Print best months for travel
print("Best months for travel:")
print(best_months[['date', 'good_weather']])
코드 해설
이 코드는 WeatherAPI.com을 사용하여 제주도의 1년간 날씨 데이터를 수집하고 분석하여 여행하기 좋은 달을 찾는 프로그램입니다. 주요 기능은 다음과 같습니다.
1. API를 통한 데이터 수집
- WeatherAPI.com에서 제주도의 지난 1년 날씨 데이터를 일별로 요청합니다.
- 각 날짜에 대해 평균 기온, 최대 풍속, 평균 습도를 수집합니다.
2. 데이터 처리
- 수집된 데이터를 pandas DataFrame으로 변환합니다.
- ‘좋은 날씨’ 조건을 정의하고 각 날짜에 대해 평가합니다 (기온 20-28°C, 풍속 15km/h 미만, 구름량 50% 미만).
3. 데이터 분석
- 월별 평균 기온, 풍속, 구름량을 계산합니다.
- ‘좋은 날씨’ 조건을 만족하는 날의 수를 월별로 집계합니다.
4. 시각화
- matplotlib를 사용하여 월별 평균 기온, 풍속, 구름량을 그래프로 표시합니다.
- 각 그래프에 기준선을 추가하여 ‘좋은 날씨’ 조건을 시각화합니다.
- 여행하기 좋은 달을 그래프에 표시합니다.
5. 결과 출력
- 여행하기 좋은 달과 해당 달의 ‘좋은 날씨’ 일수를 출력합니다. 아래 출력값을 보면 1월, 11월/12월, 2월, 3월 순서로 좋은 날씨를 만족하는 날 수가 많은 것을 볼 수 있습니다.
결과로 보는 제주도 여행하기 좋은 달
자, 이제 결과를 볼 시간이에요! 그래프를 보니 제주도 여행하기 좋은 달이 눈에 띄네요. (그런데 월별 평균온도가 조금 우리가 체감하는 것도 다른 것 같습니다.) 위 그림을 기반으로 보면 대략 11월 정도가 늦가을 정도로 해서 괜찮아 보이네요.
1. 월별 평균 온도 (첫 번째 그래프)
- 여행에 좋은 온도 범위: 20°C ~ 28°C (빨간 점선으로 표시)
- 결과:
- 2024년 1월, 2월, 3월, 11월, 12월의 평균 온도가 이 범위에 속합니다.
특히 12월과 1월의 온도는 24°C 근처로 쾌적합니다.
2. 월별 평균 풍속 (두 번째 그래프)
- 여행에 적합한 풍속 기준: 15 km/h 미만 (빨간 점선으로 표시)
- 결과:
- 풍속이 15 km/h 이하인 달은 2023년 12월, 2024년 1월, 2월, 11월, 12월입니다.
- 특히 11월과 12월은 가장 낮은 풍속을 기록했습니다.
3. 월별 평균 구름량 (세 번째 그래프)
- 여행에 적합한 구름량 기준: 50% 미만 (빨간 점선으로 표시)
- 결과:
- 구름량이 50% 미만인 달은 2023년 12월, 2024년 1월, 2월, 3월, 11월, 12월입니다.
- 1월, 2월, 3월은 특히 구름량이 매우 낮아 맑은 날이 많았습니다.
마무리
여러분, 이제 제주도 여행하기 좋은 달을 데이터로 확인해봤어요. 물론 개인의 선호도나 특별한 이벤트 등 다른 요소들도 고려해야 하지만, 이 데이터는 여행 계획에 큰 도움이 될 거예요.
제주도 여행을 계획 중이신가요? 이 정보를 참고해서 최고의 시기에 최고의 추억을 만드세요! 여러분의 제주도 여행이 환상적이길 바랄게요. 다음에 또 다른 여행 팁으로 찾아뵐게요.
혹시, API를 이용해서 데이터 분석 및 시각화한 또 다른 사례는 Python과 CryptoCompare API로 30일간의 비트코인 달러 차트 분석하기를 참고해 보시기 바랍니다.
# 코드 상세 해설
import requests import pandas as pd import matplotlib.pyplot as plt from datetime import datetime, timedelta from time import sleep
필요한 라이브러리들을 임포트합니다. requests는 API 요청, pandas는 데이터 처리, matplotlib은 시각화, datetime은 날짜 처리, time은 API 요청 간 대기 시간을 위해 사용됩니다.
api_key = 'YOUR_API_KEY'
WeatherAPI.com에서 발급받은 API 키를 설정합니다. 실제 사용 시 이 부분을 본인의 API 키로 교체해야 합니다.
full_weather_data = []
날씨 데이터를 저장할 빈 리스트를 초기화합니다.
end_date = datetime.now() start_date = end_date - timedelta(days=365)
데이터 수집 기간을 설정합니다. 현재 날짜부터 1년 전까지의 기간을 대상으로 합니다.
for date in pd.date_range(start=start_date, end=end_date):
설정된 기간 동안 날짜별로 반복합니다.
url = f"http://api.weatherapi.com/v1/history.json?key={api_key}&q=Jeju&dt={date.strftime('%Y-%m-%d')}"
각 날짜에 대한 API 요청 URL을 생성합니다.
try: response = requests.get(url) if response.status_code == 200:
API에 요청을 보내고 응답이 성공적인지 확인합니다.
data = response.json() forecast_day = data['forecast']['forecastday'][0]['day']
응답 데이터를 JSON 형식으로 파싱하고 필요한 일일 예보 데이터를 추출합니다.
full_weather_data.append({ 'date': date.strftime('%Y-%m-%d'), 'temp': forecast_day['avgtemp_c'], 'wind_speed': forecast_day['maxwind_kph'], 'cloud_cover': forecast_day['avghumidity'] })
추출한 데이터를 딕셔너리 형태로 full_weather_data 리스트에 추가합니다.
print(f"Data for {date.strftime('%Y-%m-%d')} successfully added") else: print(f"Failed to fetch data for {date.strftime('%Y-%m-%d')}. Status code: {response.status_code}") except Exception as e: print(f"Error occurred while requesting data for {date.strftime('%Y-%m-%d')}: {e}")
데이터 추가 성공 여부를 출력하고, 실패 시 에러 메시지를 출력합니다.
sleep(1)
API 요청 제한을 고려하여 각 요청 사이에 1초간 대기합니다.
df = pd.DataFrame(full_weather_data) df['date'] = pd.to_datetime(df['date'])
수집된 데이터를 pandas DataFrame으로 변환하고, 날짜 열을 datetime 형식으로 변환합니다.
df['good_weather'] = (df['temp'].between(20, 28) & (df['wind_speed'] < 15) & (df['cloud_cover'] < 50))
‘좋은 날씨’ 조건을 정의하고 각 날짜에 대해 평가합니다.
monthly_data = df.groupby(df['date'].dt.to_period('M')).agg({ 'temp': 'mean', 'wind_speed': 'mean', 'cloud_cover': 'mean', 'good_weather': 'sum' }).reset_index() monthly_data['date'] = monthly_data['date'].dt.to_timestamp()
월별 평균 데이터를 계산하고, ‘good_weather’ 조건을 만족하는 날의 수를 집계합니다.
plt.figure(figsize=(15, 12))
전체 그래프의 크기를 설정합니다.
best_months = monthly_data[monthly_data['good_weather'] > 0]
‘good_weather’ 날이 하나 이상인 달을 ‘최고의 달’로 선정합니다.
이후의 코드는 세 개의 서브플롯(기온, 풍속, 구름량)을 생성하고, 각각에 데이터를 플롯하며, ‘최고의 달’을 표시합니다. 마지막으로, 그래프를 표시하고 ‘최고의 달’ 정보를 출력합니다.