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))