kma-data-api/analyze_relative_error.py

60 lines
2.3 KiB
Python

import pandas as pd
import numpy as np
import glob
# 1. 대상 파일 목록
files = [f for f in glob.glob('weather_data_*.csv') if 'definition' not in f]
all_rel_errors = []
for file in files:
df = pd.read_csv(file)
# 0인 풍속 제외 (상대 오차 계산 불능)
df = df[df['ws_10m'] > 0.1].copy()
wd_rad = np.radians(df['wd_10m'])
ws = df['ws_10m']
u_calc = -ws * np.sin(wd_rad)
v_calc = -ws * np.cos(wd_rad)
# 개별 성분 상대 오차 (분모 0 방지를 위해 abs(rec) > 0.1 인 경우만)
u_rel = np.abs(u_calc - df['uu']) / np.abs(df['uu']).replace(0, np.nan)
v_rel = np.abs(v_calc - df['vv']) / np.abs(df['vv']).replace(0, np.nan)
# 벡터 상대 오차 (Vector Relative Error: 오차 벡터 크기 / 실제 풍속)
vec_error_mag = np.sqrt((u_calc - df['uu'])**2 + (v_calc - df['vv'])**2)
vec_rel_error = vec_error_mag / ws
# 결과 수집
df['u_rel_err'] = u_rel
df['v_rel_err'] = v_rel
df['vec_rel_err'] = vec_rel_error
all_rel_errors.append(df[['u_rel_err', 'v_rel_err', 'vec_rel_err']])
# 2. 통계 계산
total_df = pd.concat(all_rel_errors)
print("[상대 오차(Relative Error) 분석 결과]")
print("-" * 40)
print(f"1. U 성분 평균 상대오차: {total_df['u_rel_err'].mean() * 100:.2f}%")
print(f" U 성분 최대 상대오차: {total_df['u_rel_err'].max() * 100:.2f}%")
print("-" * 40)
print(f"2. V 성분 평균 상대오차: {total_df['v_rel_err'].mean() * 100:.2f}%")
print(f" V 성분 최대 상대오차: {total_df['v_rel_err'].max() * 100:.2f}%")
print("-" * 40)
print(f"3. 벡터 전체 평균 상대오차: {total_df['vec_rel_err'].mean() * 100:.2f}%")
print(f" 벡터 전체 최대 상대오차: {total_df['vec_rel_err'].max() * 100:.2f}%")
print("-" * 40)
# 오차가 큰 샘플 확인
df_sample = pd.read_csv(files[0])
df_sample['wd_rad'] = np.radians(df_sample['wd_10m'])
df_sample['u_calc'] = -df_sample['ws_10m'] * np.sin(df_sample['wd_rad'])
df_sample['u_diff'] = np.abs(df_sample['u_calc'] - df_sample['uu'])
df_sample['u_rel'] = df_sample['u_diff'] / np.abs(df_sample['uu'])
print("\n[상대 오차가 높게 나타나는 샘플 (U성분 기준)]")
print(df_sample.sort_values('u_rel', ascending=False)[['tm', 'wd_10m', 'ws_10m', 'uu', 'u_calc', 'u_rel']].head(5))