X_station Y_station distance
1 왜관 낙동강(해평) 4384.7151
2 구미 낙동강(해평) 7244.5264
3 칠곡 낙동강(해평) 1383.9565
4 계성천 낙동강(칠서) 5584.1067
5 남지 낙동강(칠서) 5918.8263
6 광려천4 낙동강(칠서) 2278.2567
7 광려천3 낙동강(칠서) 5953.9450
8 북면 낙동강(칠서) 9909.8165
9 임해진 낙동강(칠서) 6587.0792
10 함안 낙동강(칠서) 1994.1537
11 동창천1 운문호(댐앞) 6032.2489
12 부일천 운문호(댐앞) 2297.5445
13 동창천1 운문호(취수탑2) 2923.1594
14 부일천 운문호(취수탑2) 4023.0454
15 죽장천 영천호(취수탑) 3569.8502
16 금호강1 영천호(취수탑) 7893.7474
17 자호천 영천호(취수탑) 4970.1683
18 사천천(가화천) 진양호(내동) 9636.7895
19 남강1 진양호(내동) 4493.3213
20 기계천 안계호(취수탑) 3544.4620
21 형산강4 안계호(취수탑) 5193.1437
22 형산강5 안계호(취수탑) 9912.1072
23 칠성천 안계호(취수탑) 9882.3792
24 형산강6 안계호(취수탑) 9544.3270
25 금호강5 공산지(중앙부) 6832.6274
26 금호강6 공산지(중앙부) 6750.7370
27 팔거천1 공산지(중앙부) 8227.7993
28 금호강5 공산지(취수탑) 6832.6274
29 금호강6 공산지(취수탑) 6750.7370
30 팔거천1 공산지(취수탑) 8227.7993
31 형산강4 진전지(상류) 7641.9041
32 형산강5 진전지(상류) 2466.6899
33 칠성천 진전지(상류) 2099.7901
34 형산강6 진전지(상류) 1993.3080
35 냉천 진전지(상류) 4092.0456
36 형산강4 진전지(하류) 7641.9041
37 형산강5 진전지(하류) 2466.6899
38 칠성천 진전지(하류) 2099.7901
39 형산강6 진전지(하류) 1993.3080
40 냉천 진전지(하류) 4092.0456
41 작동교 사연호(취수탑) 6937.8519
42 하잠교 사연호(취수탑) 7247.6983
43 대곡천2 사연호(취수탑) 4904.7839
44 대곡천1 사연호(취수탑) 9788.2693
45 구영 사연호(취수탑) 4400.7306
46 망성 사연호(취수탑) 2530.1930
47 지헌 사연호(취수탑) 9568.7507
48 대암 사연호(취수탑) 3502.4223
49 반송 사연호(취수탑) 6046.3398
50 삼호 사연호(취수탑) 6924.8789
51 태화 사연호(취수탑) 9581.9264
52 신화 사연호(취수탑) 7584.9221
53 보은천 사연호(반연리) 9330.9434
54 작동교 사연호(반연리) 6675.5206
55 하잠교 사연호(반연리) 6699.2737
56 대곡천2 사연호(반연리) 4033.3111
57 대곡천1 사연호(반연리) 9374.1904
58 구영 사연호(반연리) 5929.8952
59 망성 사연호(반연리) 4026.4527
60 지헌 사연호(반연리) 7993.8597
61 대암 사연호(반연리) 3297.7351
62 반송 사연호(반연리) 4964.1351
63 삼호 사연호(반연리) 8462.7388
64 신화 사연호(반연리) 6449.0003
65 남강3 진양호(판문) 8366.9210
66 남강1 진양호(판문) 2855.0794
67 남강2 진양호(판문) 7182.5990
68 화원나루 낙동강(강정·고령) 4342.7659
69 용암 낙동강(강정·고령) 6913.7991
70 다사 낙동강(강정·고령) 971.2662
71 달성 낙동강(강정·고령) 870.3569
72 하빈천 낙동강(강정·고령) 4524.3799
73 백천2 낙동강(강정·고령) 7966.7647
74 성주 낙동강(강정·고령) 7280.3273
75 금호강8 낙동강(강정·고령) 933.9527
76 금호강7 낙동강(강정·고령) 9255.4695
77 양산천3 낙동강(물금·매리) 9142.6852
78 금곡 낙동강(물금·매리) 9726.1338
79 양산천2 낙동강(물금·매리) 9522.4986
80 물금 낙동강(물금·매리) 4859.0376
81 병성천 상주보(도남) 2156.7596
82 영강2 상주보(도남) 8997.4434
83 영강3 상주보(도남) 9835.0394
84 이안천 상주보(도남) 9729.4609
85 위천5 상주보(도남) 8165.2211
86 도남 상주보(도남) 1602.0051
87 상주1 상주보(도남) 5401.2399
88 영순 상주보(도남) 9821.6805
89 상주2 상주보(도남) 6711.6791
90 말지천 상주보(도남) 7148.5729
91 병성천 낙단보(낙단) 9900.6842
92 위천5 낙단보(낙단) 3875.4852
93 위천4 낙단보(낙단) 8008.6399
94 낙단 낙단보(낙단) 515.1861
95 상주3 낙단보(낙단) 1040.7046
96 도남 낙단보(낙단) 9127.1488
97 상주2 낙단보(낙단) 4599.3465
98 말지천 낙단보(낙단) 7076.6262
99 감천4 구미보(선산) 3130.4480
100 감천3 구미보(선산) 2232.8781
101 강정 구미보(선산) 6512.8837
102 산곡 구미보(선산) 507.6795
103 선산 구미보(선산) 3227.8035
104 왜관 칠곡보(칠곡) 4384.7151
105 구미 칠곡보(칠곡) 7244.5264
106 칠곡 칠곡보(칠곡) 1383.9565
107 화원나루 강정고령보(다사) 4342.7659
108 용암 강정고령보(다사) 6913.7991
109 다사 강정고령보(다사) 971.2662
110 달성 강정고령보(다사) 870.3569
111 하빈천 강정고령보(다사) 4524.3799
112 백천2 강정고령보(다사) 7966.7647
113 성주 강정고령보(다사) 7280.3273
114 금호강8 강정고령보(다사) 933.9527
115 금호강7 강정고령보(다사) 9255.4695
116 화원나루 달성보(논공) 8228.6506
117 고령 달성보(논공) 3722.0625
118 논공 달성보(논공) 1529.6040
119 차천 달성보(논공) 5711.2884
120 현풍 달성보(논공) 4987.4547
121 창녕 합천창녕보(덕곡) 1149.0893
122 덕곡 합천창녕보(덕곡) 1716.0470
123 대암리 합천창녕보(덕곡) 2041.0828
124 황강5 합천창녕보(덕곡) 5693.3845
125 황강6 합천창녕보(덕곡) 3257.4492
126 회천2 합천창녕보(덕곡) 8573.0313
127 회천3 합천창녕보(덕곡) 1689.4414
128 토평천2 합천창녕보(덕곡) 9792.7734
129 합천 합천창녕보(덕곡) 9227.8056
130 계성천 창녕함안보(함안) 5584.1067
131 남지 창녕함안보(함안) 5918.8263
132 광려천4 창녕함안보(함안) 2278.2567
133 광려천3 창녕함안보(함안) 5953.9450
134 북면 창녕함안보(함안) 9909.8165
135 임해진 창녕함안보(함안) 6587.0792
136 함안 창녕함안보(함안) 1994.1537
137 화원나루 낙동강_시범(고령 지점 표층) 5948.6434
138 용암 낙동강_시범(고령 지점 표층) 3049.1896
139 다사 낙동강_시범(고령 지점 표층) 3242.9403
140 달성 낙동강_시범(고령 지점 표층) 3913.0596
141 하빈천 낙동강_시범(고령 지점 표층) 1179.6962
142 백천2 낙동강_시범(고령 지점 표층) 4289.5010
143 성주 낙동강_시범(고령 지점 표층) 3613.5662
144 금호강8 낙동강_시범(고령 지점 표층) 4659.1071
145 화원나루 낙동강_시범(고령 지점 혼합) 5948.6434
146 용암 낙동강_시범(고령 지점 혼합) 3049.1896
147 다사 낙동강_시범(고령 지점 혼합) 3242.9403
148 달성 낙동강_시범(고령 지점 혼합) 3913.0596
149 하빈천 낙동강_시범(고령 지점 혼합) 1179.6962
150 백천2 낙동강_시범(고령 지점 혼합) 4289.5010
151 성주 낙동강_시범(고령 지점 혼합) 3613.5662
152 금호강8 낙동강_시범(고령 지점 혼합) 4659.1071
153 양산천3 낙동강_시범(매리 지점 표층) 5508.4699
154 금곡 낙동강_시범(매리 지점 표층) 5940.3160
155 서낙동강1 낙동강_시범(매리 지점 표층) 8961.3041
156 양산천2 낙동강_시범(매리 지점 표층) 8352.3129
157 물금 낙동강_시범(매리 지점 표층) 1735.4020
158 양산천3 낙동강_시범(매리 지점 혼합) 5508.4699
159 금곡 낙동강_시범(매리 지점 혼합) 5940.3160
160 서낙동강1 낙동강_시범(매리 지점 혼합) 8961.3041
161 양산천2 낙동강_시범(매리 지점 혼합) 8352.3129
162 물금 낙동강_시범(매리 지점 혼합) 1735.4020
163 고령 낙동강_시범(레포츠밸리) 6920.4160
164 논공 낙동강_시범(레포츠밸리) 6816.0377
165 창녕 낙동강_시범(레포츠밸리) 8462.1694
166 대암리 낙동강_시범(레포츠밸리) 8449.5022
167 차천 낙동강_시범(레포츠밸리) 4481.8874
168 현풍 낙동강_시범(레포츠밸리) 5168.2026
169 회천2 낙동강_시범(레포츠밸리) 3030.7755
170 회천3 낙동강_시범(레포츠밸리) 8094.6032
171 구미 낙동강_시범(구미낙동강레포츠체험센터) 4423.2474
172 한천2 낙동강_시범(구미낙동강레포츠체험센터) 2015.3628
173 한천1 낙동강_시범(구미낙동강레포츠체험센터) 7826.4038
174 하남 낙동강_시범(본포수변생태공원) 5007.9004
175 주천강 낙동강_시범(본포수변생태공원) 9458.0901
176 북면 낙동강_시범(본포수변생태공원) 822.7867
177 임해진 낙동강_시범(본포수변생태공원) 5236.8673
178 주항천 낙동강_시범(본포수변생태공원) 9518.3995
179 청도천1 낙동강_시범(본포수변생태공원) 8139.3987
180 청도천2 낙동강_시범(본포수변생태공원) 6347.7722
181 함안 낙동강_시범(본포수변생태공원) 9015.5875
182 양산천3 낙동강_시범(화명수상레포츠타운) 8226.2280
183 금곡 낙동강_시범(화명수상레포츠타운) 7126.5616
184 구포 낙동강_시범(화명수상레포츠타운) 2253.1533
185 서낙동강1 낙동강_시범(화명수상레포츠타운) 6666.6538 Y_station min_distance_X_station min_distance
1 강정고령보(다사) 달성 870.3569
2 공산지(중앙부) 금호강6 6750.7370
3 공산지(취수탑) 금호강6 6750.7370
4 구미보(선산) 산곡 507.6795
5 낙단보(낙단) 낙단 515.1861
6 낙동강(강정·고령) 달성 870.3569
7 낙동강(물금·매리) 물금 4859.0376
8 낙동강(칠서) 함안 1994.1537
9 낙동강(해평) 칠곡 1383.9565
10 낙동강_시범(고령 지점 표층) 하빈천 1179.6962
11 낙동강_시범(고령 지점 혼합) 하빈천 1179.6962
12 낙동강_시범(구미낙동강레포츠체험센터) 한천2 2015.3628
13 낙동강_시범(레포츠밸리) 회천2 3030.7755
14 낙동강_시범(매리 지점 표층) 물금 1735.4020
15 낙동강_시범(매리 지점 혼합) 물금 1735.4020
16 낙동강_시범(본포수변생태공원) 북면 822.7867
17 낙동강_시범(화명수상레포츠타운) 구포 2253.1533
18 달성보(논공) 논공 1529.6040
19 사연호(반연리) 대암 3297.7351
20 사연호(취수탑) 망성 2530.1930
21 상주보(도남) 도남 1602.0051
22 안계호(취수탑) 기계천 3544.4620
23 영천호(취수탑) 죽장천 3569.8502
24 운문호(댐앞) 부일천 2297.5445
25 운문호(취수탑2) 동창천1 2923.1594
26 진양호(내동) 남강1 4493.3213
27 진양호(판문) 남강1 2855.0794
28 진전지(상류) 형산강6 1993.3080
29 진전지(하류) 형산강6 1993.3080
30 창녕함안보(함안) 함안 1994.1537
31 칠곡보(칠곡) 칠곡 1383.9565
32 합천창녕보(덕곡) 창녕 1149.0893낙동강(해평) | 경상북도 칠곡군 석적읍 중지리 | 낙동강물환경연구소 |
낙동강(칠서) | 경상남도 함안군 칠북면 이령리 | 낙동강물환경연구소 |
운문호(댐앞) | 경상북도 청도군 운문면 대천리 | 대구지방환경청 |
운문호(취수탑2) | 경상북도 청도군 운문면 서지리 | 대구지방환경청 |
영천호(취수탑) | 경상북도 영천시 자양면 삼귀리 | 대구지방환경청 |
진양호(내동) | 경상남도 사천시 곤명면 연평리 | 낙동강유역환경청 |
안계호(취수탑) | 경상북도 경주시 강동면 안계리 | 대구지방환경청 |
공산지(중앙부) | 대구광역시 동구 지묘동 | 대구시 상수도사업본부 |
공산지(취수탑) | 대구광역시 동구 지묘동 | 대구시 상수도사업본부 |
진전지(상류) | 경상북도 포항시 남구 연일읍 오천리 | 경상북도 보건환경연구원 |
진전지(하류) | 경상북도 포항시 남구 연일읍 오천리 | 경상북도 보건환경연구원 |
사연호(취수탑) | 울산광역시 울주군 범서읍 사연리 | 낙동강유역환경청 |
사연호(반연리) | 울산광역시 울주군 언양읍 반연리 | 낙동강유역환경청 |
덕동호(댐앞) | 경상북도 경주시 덕동 | 낙동강물환경연구소 |
낙동강(물금·매리) | 경상남도 김해시 상동면 감노리 | 낙동강물환경연구소 |
진양호(판문) | 경상남도 진주시 판문동 | 낙동강유역환경청 |
낙동강(강정·고령) | 대구광역시 달성군 다사읍 죽곡리 | 낙동강물환경연구소 |
file_path = 'Datasets/XY_cnhaman_1vs1_3.csv'
drop_cols = ['연도', '월', '조사회차', '수계.명',"longitude.x","latitude.x","분류","지점명","채수위치","수온","addr","location","no","latitude.y","longitude.y"]
time_col = '채수.일자'
zero_cols = ["Microcystis", "Anabaena", "Oscillatoria", "Aphanizomenon"]
df = load_data(file_path, drop_cols, time_col, zero_cols)
df.info()target = '유해남조류.세포수..cells...'
numeric_cols = df.select_dtypes(include=['number']).columns
fig, axes = plt.subplots(nrows=len(numeric_cols), ncols=1, figsize=(12, 3 * len(df.columns)), sharex=True)
for i, col in enumerate(numeric_cols):
axes[i].plot(df.index, df[col], label=col, color='tab:blue')
axes[i].set_ylabel(col)
axes[i].legend(loc='upper right')
axes[i].grid(True)
plt.xlabel("Date")
plt.tight_layout()
plt.show()numeric_columns = df.select_dtypes(include=[np.number]).columns.tolist()
corr_matrix = df[numeric_columns].corr()
print("Correlation matrix : ")
print(corr_matrix)
plt.figure(figsize=(18, 18))
sns.heatmap(corr_matrix, annot=True, fmt=".2f", cmap='coolwarm', square=True, cbar_kws={"shrink": .8})
plt.title('Correlation Matrix')def month_to_season(month):
if month in [3, 4, 5]:
return 'Spring'
elif month in [6, 7, 8]:
return 'Summer'
elif month in [9, 10, 11]:
return 'Autumn'
else: # 12, 1, 2
return 'Winter'
df['year'] = df.index.year
df['month'] = df.index.month
df['season'] = df['month'].apply(month_to_season)plt.figure(figsize=(6,4))
years= range(2016, 2025)
data = [df[df['year']==y][target] for y in years]
plt.boxplot(data, labels=years)
plt.title('연도별 유해 남조류 수 분포')
plt.ylabel('µg/L')
plt.tight_layout()
plt.show()plt.figure(figsize=(6,4))
months = range(1, 13)
data = [df[df['month']==m][target] for m in months]
plt.boxplot(data, labels=months)
plt.title('월별 유해 남조류 수 분포')
plt.ylabel('µg/L')
plt.tight_layout()
plt.show()plt.figure(figsize=(6,4))
seasons = ['Spring','Summer','Autumn','Winter']
data = [df[df['season']==s][target] for s in seasons]
plt.boxplot(data, labels=seasons)
plt.title('계절별 유해 남조류 수 분포')
plt.ylabel('µg/L')
plt.tight_layout()
plt.show()from statsmodels.tsa.stattools import ccf
def decompose_and_plot(ts: pd.Series, title: str, period: int = 365):
"""
시계열 분해(추세, 계절성, 잔차) 및 플롯
- ts: DatetimeIndex를 갖는 pandas Series
- title: 플롯 제목
- period: 계절 주기 (일 단위)
"""
decomp = seasonal_decompose(ts, model='additive', period=period)
fig, axes = plt.subplots(3, 1, figsize=(10, 8), sharex=True)
decomp.trend.plot(ax=axes[0], title=f'{title} — 추세')
decomp.seasonal.plot(ax=axes[1], title=f'{title} — 계절성')
decomp.resid.plot(ax=axes[2], title=f'{title} — 잔차')
plt.tight_layout()
plt.show()
def plot_ccf(series_x: pd.Series, series_y: pd.Series, max_lag: int = 60, title: str = 'CCF'):
"""
두 시계열 간 교차상관함수(CCF) 플롯
- series_x: 선행(화학 변수)
- series_y: 결과(Bloom)
"""
x = series_x.values
y = series_y.values
c = ccf(x, y)[:max_lag]
plt.figure(figsize=(6, 3))
plt.stem(range(len(c)), c)
plt.title(title)
plt.xlabel('Lag (days)')
plt.ylabel('Cross-correlation')
plt.tight_layout()
plt.show()
# 3) 시계열 분해 및 플롯
decompose_and_plot(df[target], '낙동강 유해남조류 수', period=4*12)# 4) 주요 화학 변수 vs Bloom CCF 분석
chem_vars = ['클로로필.a.Chlorophyll.a.', '수온...']
for var in numeric_cols:
plot_ccf(df[var], df[target], max_lag=60, title=f'CCF: {var} → 유해남조류 수')
def crate_dataset(df, train_ratio, target, features=None):
n = len(df)
train_size = int(n*train_ratio)
if features:
X = df[features]
y = df[target]
X_train = X[:train_size]
X_test = X[train_size:]
y_train = y[:train_size]
y_test = y[train_size:]
return X_train, y_train, X_test, y_test
else:
data = df[target]
train = data[:train_size]
test = data[train_size:]
return train, testdef check_stationarity(data):
adf = adfuller(data)
print(f"ADF Statistic: {adf[0]}")
print(f"p-value: {adf[1]}")
print(f"Critical Values: {adf[4]}")
if adf[1] < 0.01:
print("정상성")
else:
print("비정상성")
fig, ax = plt.subplots(1, 2 ,figsize = (12, 5))
plot_acf(data.diff().dropna(), ax = ax[0])
plot_pacf(data.diff().dropna(), ax = ax[1])
plt.show()paths = 'Datasets/XY_cnhaman_1vs1_3.csv'
df = pd.read_csv(paths, index_col=0)
df.head()
연도 월 조사회차 채수.일자 수계.명 중권역.명 측정소.명 수심 음이온계면활성제.ABS. 유량 ... Microcystin.RR Microcystin.LA Microcystin.YR Microcystin.LF Microcystin.LY location addr no latitude.y longitude.y
1 2016.0 1.0 1회차 2016-01-04 낙동강 낙동밀양 함안 NaN NaN NaN ... NaN NaN NaN NaN NaN 창녕함안보(함안) 경상남도 함안군 칠북면 이령리 36.0 35.366363 128.536973
2 2016.0 1.0 2회차 2016-01-11 낙동강 낙동밀양 함안 NaN NaN NaN ... NaN NaN NaN NaN NaN 창녕함안보(함안) 경상남도 함안군 칠북면 이령리 36.0 35.366363 128.536973
3 2016.0 1.0 3회차 2016-01-18 낙동강 낙동밀양 함안 NaN NaN NaN ... NaN NaN NaN NaN NaN 창녕함안보(함안) 경상남도 함안군 칠북면 이령리 36.0 35.366363 128.536973
4 2016.0 1.0 4회차 2016-01-26 낙동강 낙동밀양 함안 NaN NaN NaN ... NaN NaN NaN NaN NaN 창녕함안보(함안) 경상남도 함안군 칠북면 이령리 36.0 35.366363 128.536973
5 2016.0 2.0 1회차 2016-02-01 낙동강 낙동밀양 함안 NaN NaN NaN ... NaN NaN NaN NaN NaN 창녕함안보(함안) 경상남도 함안군 칠북면 이령리 36.0 35.366363 128.536973
5 rows × 93 columnsdrop_cols = ['연도', '월', '조사회차', '수계.명',"longitude.x","latitude.x","분류","지점명","채수위치","수온","addr","location","no","latitude.y","longitude.y"]
df.drop(drop_cols, axis=1, inplace=True)
df['채수.일자'] = pd.to_datetime(df['채수.일자'])
df = df.set_index('채수.일자')
df.head()
중권역.명 측정소.명 수심 음이온계면활성제.ABS. 유량 안티몬.Sb. 비소.As. 바륨.Ba. 벤젠 생물화학적산소요구량.BOD. ... Oscillatoria Aphanizomenon 지오스민 X2MIB Microcystin.LR Microcystin.RR Microcystin.LA Microcystin.YR Microcystin.LF Microcystin.LY
채수.일자
2016-01-04 낙동밀양 함안 NaN NaN NaN NaN NaN NaN NaN 3.6 ... NaN NaN 16.0 NaN NaN NaN NaN NaN NaN NaN
2016-01-11 낙동밀양 함안 NaN NaN NaN NaN NaN NaN NaN 1.8 ... NaN NaN 14.0 NaN NaN NaN NaN NaN NaN NaN
2016-01-18 낙동밀양 함안 NaN NaN NaN NaN NaN NaN NaN 1.3 ... NaN NaN 16.0 NaN NaN NaN NaN NaN NaN NaN
2016-01-26 낙동밀양 함안 NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2016-02-01 낙동밀양 함안 NaN NaN NaN NaN NaN NaN NaN 1.1 ... NaN NaN 13.0 NaN NaN NaN NaN NaN NaN NaN
5 rows × 77 columnszero_cols = ["Microcystis", "Anabaena", "Oscillatoria", "Aphanizomenon"]
df[zero_cols] = df[zero_cols].fillna(0)df.info()<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 494 entries, 2016-01-04 to 2025-05-07
Data columns (total 77 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 중권역.명 470 non-null object
1 측정소.명 470 non-null object
2 수심 0 non-null float64
3 음이온계면활성제.ABS. 0 non-null float64
4 유량 0 non-null float64
5 안티몬.Sb. 29 non-null float64
6 비소.As. 0 non-null float64
7 바륨.Ba. 0 non-null float64
8 벤젠 0 non-null float64
9 생물화학적산소요구량.BOD. 442 non-null float64
10 사염화탄소 0 non-null float64
11 카드뮴.Cd. 0 non-null float64
12 클로로포름 0 non-null float64
13 염소이온.Cl.. 0 non-null float64
14 클로로필.a.Chlorophyll.a. 442 non-null float64
15 시안.CN. 0 non-null float64
16 화학적산소요구량.COD. 442 non-null float64
17 색도 0 non-null float64
18 크롬.Cr. 0 non-null float64
19 X6가크롬.Cr6.. 0 non-null float64
20 구리.Cu. 0 non-null float64
21 X1.2..다이클로로에탄 0 non-null float64
22 다이클로로메탄 0 non-null float64
23 다이에틸헥실프탈레이트.DEHP. 0 non-null float64
24 X1.4.다이옥세인 0 non-null float64
25 용존산소.DO. 442 non-null float64
26 용존총질소.DTN. 442 non-null float64
27 용존총인.DTP. 442 non-null float64
28 전기전도도.EC. 442 non-null float64
29 분원성대장균군 442 non-null float64
30 용해성.철.Fe. 0 non-null float64
31 불소.F. 0 non-null float64
32 헥사클로로벤젠 0 non-null float64
33 포름알데히드 0 non-null float64
34 수은.Hg. 0 non-null float64
35 용해성.망간.Mn. 0 non-null float64
36 암모니아성.질소.NH3.N. 441 non-null float64
37 노말헥산추출물질 0 non-null float64
38 니켈.Ni. 0 non-null float64
39 질산성질소.NO3.N. 442 non-null float64
40 유기인 0 non-null float64
41 납.Pb. 0 non-null float64
42 폴리클로리네이티드비페닐.PCB. 0 non-null float64
43 테트라클로로에틸렌.PCE. 0 non-null float64
44 수소이온농도.pH. 442 non-null float64
45 페놀류.phenols. 0 non-null float64
46 인산염.인.PO4.P. 243 non-null float64
47 셀레늄.Se. 0 non-null float64
48 부유물질.SS. 442 non-null float64
49 트리클로로에틸렌.TCE. 0 non-null float64
50 총대장균군 442 non-null float64
51 총질소.T.N. 442 non-null float64
52 총유기탄소.TOC. 442 non-null float64
53 총인.T.P. 442 non-null float64
54 투명도.x 0 non-null float64
55 아연.Zn. 0 non-null float64
56 TYPE 470 non-null object
57 PTNO 470 non-null object
58 수온... 457 non-null float64
59 pH 457 non-null float64
60 DO...L. 457 non-null float64
61 투명도.y 235 non-null float64
62 탁도 235 non-null float64
63 Chl.a...... 457 non-null float64
64 유해남조류.세포수..cells... 457 non-null float64
65 Microcystis 494 non-null float64
66 Anabaena 494 non-null float64
67 Oscillatoria 494 non-null float64
68 Aphanizomenon 494 non-null float64
69 지오스민 208 non-null float64
70 X2MIB 99 non-null float64
71 Microcystin.LR 0 non-null float64
72 Microcystin.RR 0 non-null float64
73 Microcystin.LA 0 non-null float64
74 Microcystin.YR 0 non-null float64
75 Microcystin.LF 0 non-null float64
76 Microcystin.LY 0 non-null float64
dtypes: float64(73), object(4)
memory usage: 301.0+ KBdf = df.dropna(axis=0, thresh=20)
df.info()<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 442 entries, 2016-01-04 to 2025-02-24
Data columns (total 77 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 중권역.명 442 non-null object
1 측정소.명 442 non-null object
2 수심 0 non-null float64
3 음이온계면활성제.ABS. 0 non-null float64
4 유량 0 non-null float64
5 안티몬.Sb. 29 non-null float64
6 비소.As. 0 non-null float64
7 바륨.Ba. 0 non-null float64
8 벤젠 0 non-null float64
9 생물화학적산소요구량.BOD. 442 non-null float64
10 사염화탄소 0 non-null float64
11 카드뮴.Cd. 0 non-null float64
12 클로로포름 0 non-null float64
13 염소이온.Cl.. 0 non-null float64
14 클로로필.a.Chlorophyll.a. 442 non-null float64
15 시안.CN. 0 non-null float64
16 화학적산소요구량.COD. 442 non-null float64
17 색도 0 non-null float64
18 크롬.Cr. 0 non-null float64
19 X6가크롬.Cr6.. 0 non-null float64
20 구리.Cu. 0 non-null float64
21 X1.2..다이클로로에탄 0 non-null float64
22 다이클로로메탄 0 non-null float64
23 다이에틸헥실프탈레이트.DEHP. 0 non-null float64
24 X1.4.다이옥세인 0 non-null float64
25 용존산소.DO. 442 non-null float64
26 용존총질소.DTN. 442 non-null float64
27 용존총인.DTP. 442 non-null float64
28 전기전도도.EC. 442 non-null float64
29 분원성대장균군 442 non-null float64
30 용해성.철.Fe. 0 non-null float64
31 불소.F. 0 non-null float64
32 헥사클로로벤젠 0 non-null float64
33 포름알데히드 0 non-null float64
34 수은.Hg. 0 non-null float64
35 용해성.망간.Mn. 0 non-null float64
36 암모니아성.질소.NH3.N. 441 non-null float64
37 노말헥산추출물질 0 non-null float64
38 니켈.Ni. 0 non-null float64
39 질산성질소.NO3.N. 442 non-null float64
40 유기인 0 non-null float64
41 납.Pb. 0 non-null float64
42 폴리클로리네이티드비페닐.PCB. 0 non-null float64
43 테트라클로로에틸렌.PCE. 0 non-null float64
44 수소이온농도.pH. 442 non-null float64
45 페놀류.phenols. 0 non-null float64
46 인산염.인.PO4.P. 243 non-null float64
47 셀레늄.Se. 0 non-null float64
48 부유물질.SS. 442 non-null float64
49 트리클로로에틸렌.TCE. 0 non-null float64
50 총대장균군 442 non-null float64
51 총질소.T.N. 442 non-null float64
52 총유기탄소.TOC. 442 non-null float64
53 총인.T.P. 442 non-null float64
54 투명도.x 0 non-null float64
55 아연.Zn. 0 non-null float64
56 TYPE 442 non-null object
57 PTNO 442 non-null object
58 수온... 442 non-null float64
59 pH 442 non-null float64
60 DO...L. 442 non-null float64
61 투명도.y 222 non-null float64
62 탁도 222 non-null float64
63 Chl.a...... 442 non-null float64
64 유해남조류.세포수..cells... 442 non-null float64
65 Microcystis 442 non-null float64
66 Anabaena 442 non-null float64
67 Oscillatoria 442 non-null float64
68 Aphanizomenon 442 non-null float64
69 지오스민 206 non-null float64
70 X2MIB 99 non-null float64
71 Microcystin.LR 0 non-null float64
72 Microcystin.RR 0 non-null float64
73 Microcystin.LA 0 non-null float64
74 Microcystin.YR 0 non-null float64
75 Microcystin.LF 0 non-null float64
76 Microcystin.LY 0 non-null float64
dtypes: float64(73), object(4)
memory usage: 269.3+ KBdf = df.dropna(axis=1, how='any')
df.info()<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 442 entries, 2016-01-04 to 2025-02-24
Data columns (total 28 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 중권역.명 442 non-null object
1 측정소.명 442 non-null object
2 생물화학적산소요구량.BOD. 442 non-null float64
3 클로로필.a.Chlorophyll.a. 442 non-null float64
4 화학적산소요구량.COD. 442 non-null float64
5 용존산소.DO. 442 non-null float64
6 용존총질소.DTN. 442 non-null float64
7 용존총인.DTP. 442 non-null float64
8 전기전도도.EC. 442 non-null float64
9 분원성대장균군 442 non-null float64
10 질산성질소.NO3.N. 442 non-null float64
11 수소이온농도.pH. 442 non-null float64
12 부유물질.SS. 442 non-null float64
13 총대장균군 442 non-null float64
14 총질소.T.N. 442 non-null float64
15 총유기탄소.TOC. 442 non-null float64
16 총인.T.P. 442 non-null float64
17 TYPE 442 non-null object
18 PTNO 442 non-null object
19 수온... 442 non-null float64
20 pH 442 non-null float64
21 DO...L. 442 non-null float64
22 Chl.a...... 442 non-null float64
23 유해남조류.세포수..cells... 442 non-null float64
24 Microcystis 442 non-null float64
25 Anabaena 442 non-null float64
26 Oscillatoria 442 non-null float64
27 Aphanizomenon 442 non-null float64
dtypes: float64(24), object(4)
memory usage: 100.1+ KBdf = df.interpolate(method='time')
df.info()<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 442 entries, 2016-01-04 to 2025-02-24
Data columns (total 28 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 중권역.명 442 non-null object
1 측정소.명 442 non-null object
2 생물화학적산소요구량.BOD. 442 non-null float64
3 클로로필.a.Chlorophyll.a. 442 non-null float64
4 화학적산소요구량.COD. 442 non-null float64
5 용존산소.DO. 442 non-null float64
6 용존총질소.DTN. 442 non-null float64
7 용존총인.DTP. 442 non-null float64
8 전기전도도.EC. 442 non-null float64
9 분원성대장균군 442 non-null float64
10 질산성질소.NO3.N. 442 non-null float64
11 수소이온농도.pH. 442 non-null float64
12 부유물질.SS. 442 non-null float64
13 총대장균군 442 non-null float64
14 총질소.T.N. 442 non-null float64
15 총유기탄소.TOC. 442 non-null float64
16 총인.T.P. 442 non-null float64
17 TYPE 442 non-null object
18 PTNO 442 non-null object
19 수온... 442 non-null float64
20 pH 442 non-null float64
21 DO...L. 442 non-null float64
22 Chl.a...... 442 non-null float64
23 유해남조류.세포수..cells... 442 non-null float64
24 Microcystis 442 non-null float64
25 Anabaena 442 non-null float64
26 Oscillatoria 442 non-null float64
27 Aphanizomenon 442 non-null float64
dtypes: float64(24), object(4)
memory usage: 100.1+ KB
C:\Users\손보건\AppData\Local\Temp\ipykernel_33160\536553338.py:1: FutureWarning: DataFrame.interpolate with object dtype is deprecated and will raise in a future version. Call obj.infer_objects(copy=False) before interpolating instead.
df = df.interpolate(method='time')df.columnsIndex(['중권역.명', '측정소.명', '생물화학적산소요구량.BOD.', '클로로필.a.Chlorophyll.a.',
'화학적산소요구량.COD.', '용존산소.DO.', '용존총질소.DTN.', '용존총인.DTP.', '전기전도도.EC.',
'분원성대장균군', '질산성질소.NO3.N.', '수소이온농도.pH.', '부유물질.SS.', '총대장균군',
'총질소.T.N.', '총유기탄소.TOC.', '총인.T.P.', 'TYPE', 'PTNO', '수온...', 'pH',
'DO...L.', 'Chl.a......', '유해남조류.세포수..cells...', 'Microcystis',
'Anabaena', 'Oscillatoria', 'Aphanizomenon'],
dtype='object')df
중권역.명 측정소.명 생물화학적산소요구량.BOD. 클로로필.a.Chlorophyll.a. 화학적산소요구량.COD. 용존산소.DO. 용존총질소.DTN. 용존총인.DTP. 전기전도도.EC. 분원성대장균군 ... PTNO 수온... pH DO...L. Chl.a...... 유해남조류.세포수..cells... Microcystis Anabaena Oscillatoria Aphanizomenon
채수.일자
2016-01-04 낙동밀양 함안 3.6 10.1 5.7 14.5 2.429 0.018 364.0 1.0 ... 2020A32 5.5 8.2 14.5 10.1 242.0 0.0 0.0 0.0 0.0
2016-01-11 낙동밀양 함안 1.8 17.5 5.8 13.9 2.846 0.018 451.0 1.0 ... 2020A32 4.8 7.8 13.9 17.5 152.0 0.0 0.0 0.0 0.0
2016-01-18 낙동밀양 함안 1.3 12.1 5.7 12.9 3.122 0.016 452.0 0.0 ... 2020A32 4.0 7.9 12.9 12.1 254.0 0.0 0.0 0.0 0.0
2016-02-01 낙동밀양 함안 1.1 7.0 5.1 13.7 2.984 0.015 417.0 3.0 ... 2020A32 2.4 7.5 13.7 7.0 0.0 0.0 0.0 0.0 0.0
2016-02-11 낙동밀양 함안 1.9 12.8 5.3 12.0 2.617 0.013 324.0 0.0 ... 2020A32 4.0 7.4 12.0 12.8 0.0 0.0 0.0 0.0 0.0
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
2024-12-16 낙동밀양 함안 2.0 20.3 5.2 13.6 2.667 0.017 319.0 28.0 ... 2020A32 7.1 8.6 13.5 24.2 1844.0 60.0 65.0 0.0 1719.0
2024-12-23 낙동밀양 함안 2.8 32.4 6.2 15.0 2.708 0.018 338.0 19.0 ... 2020A32 5.3 9.0 15.0 41.6 2386.0 0.0 12.0 0.0 2374.0
2025-01-06 낙동밀양 함안 1.6 14.7 4.5 13.6 2.716 0.011 355.0 17.0 ... 2020A32 4.7 8.2 13.5 18.9 436.0 0.0 0.0 0.0 436.0
2025-01-13 낙동밀양 함안 1.3 10.4 4.7 13.1 2.910 0.014 364.0 9.0 ... 2020A32 3.2 8.1 12.9 11.8 522.0 0.0 0.0 0.0 522.0
2025-02-24 낙동밀양 함안 2.3 17.5 4.9 13.9 3.180 0.008 401.0 7.0 ... 2020A32 4.6 8.1 13.6 14.2 0.0 0.0 0.0 0.0 0.0
442 rows × 28 columns모델 | 구조 | 주요 설정 | 성능(Val Loss) |
FNN | Dense(256→64→1) | lr=0.001, MSE | 0.08 |
CNN | Conv1D→GAP→Dense | lr=0.0005, MSE, window=7 | 0.03 |
RNN | SimpleRNN(64→32→1) | lr=0.0005, MSE | 0.07 |
LSTM | LSTM(128→Dense(1)) | lr=0.001, Huber, window=5 | 0.05 |
Transformer | Dense 다층 + Dropout | lr=0.01 | 0.3056 |
문제 | 해결 방법 | 효과 |
낮은 예측력, 스파이크 미검출 | 시차·롤링·사이클릭 변수, 외생변수 추가 | MAE 10% 개선 |
분포 왜곡·극단치 영향 | 로그 변환 + Huber/Quantile Loss | MAE 15% 감소 |
재귀 예측 오차 누적 | Direct Multi-step Seq2Seq | 예측 안정성 확보 |
단일 모델 편향 | Weighted 앙상블 + Stacking 메타러닝 | MAE 20% 개선, 스파이크 재현 ↑ |