File PRACTICE_otchet.tex copied from file NIR_otchet.tex (similarity 51%) (mode: 100644) (index 9ed491e..5e63d8f) |
68 |
68 |
\medskip |
\medskip |
69 |
69 |
|
|
70 |
70 |
\textbf{\Large |
\textbf{\Large |
71 |
|
Разработка сценариев анализа динамики метеопараметров |
|
|
71 |
|
Разработка скриптов на языке Python для обработки и анализа метеоданных |
72 |
72 |
} |
} |
73 |
73 |
|
|
74 |
74 |
\end{center} |
\end{center} |
|
104 |
104 |
|
|
105 |
105 |
ЯЗЫК ПРОГРАММИРОВАНИЯ PYTHON, NUMPY, STATSMODELS, PANDAS, АНАЛИЗ ВРЕМЕННЫХ РЯДОВ, МЕТЕОДАННЫЕ, ВРЕМЕННЫЕ РЯДЫ. |
ЯЗЫК ПРОГРАММИРОВАНИЯ PYTHON, NUMPY, STATSMODELS, PANDAS, АНАЛИЗ ВРЕМЕННЫХ РЯДОВ, МЕТЕОДАННЫЕ, ВРЕМЕННЫЕ РЯДЫ. |
106 |
106 |
|
|
107 |
|
Научно-исследовательская работа посвящена разработке сценариев анализа динамики метеопараметров. Конечная цель работы – создание сценария на языке Python для обработки и визуализации динамики температуры и осадков. |
|
|
107 |
|
Научно-исследовательская работа посвящена разработке сценариев анализа динамики метеопараметров. Конечная цель работы – создание сценариев на языке Python для вывода значений декомпозиции метеопараметров в файл, построения графиков размаха температур и визуализации трендов и случайных составляющих данных по температуре. |
108 |
108 |
|
|
109 |
109 |
Процесс разработки включает в себя изучение методов декомпозиции временных рядов, языка прогаммирования Python, библиотеки Statsmodels, предоставляющей набор методов статистического тестирования и моделирования, библиотеки Pandas для обработки и анализа данных. |
Процесс разработки включает в себя изучение методов декомпозиции временных рядов, языка прогаммирования Python, библиотеки Statsmodels, предоставляющей набор методов статистического тестирования и моделирования, библиотеки Pandas для обработки и анализа данных. |
110 |
110 |
|
|
|
... |
... |
NumPy - Numerical Python |
137 |
137 |
|
|
138 |
138 |
\section*{\centering ВВЕДЕНИЕ} |
\section*{\centering ВВЕДЕНИЕ} |
139 |
139 |
\addcontentsline{toc}{section}{ВВЕДЕНИЕ} |
\addcontentsline{toc}{section}{ВВЕДЕНИЕ} |
140 |
|
\input{intro} % текст введения в файле intro.tex |
|
|
140 |
|
\input{intro2} % текст введения в файле intro.tex |
141 |
141 |
\pagebreak |
\pagebreak |
142 |
142 |
|
|
143 |
143 |
%\input{Post_zad} |
%\input{Post_zad} |
144 |
144 |
\pagebreak |
\pagebreak |
145 |
|
\input{part1} % первая глава - в файле part1.tex |
|
|
145 |
|
\input{part3} % первая глава - в файле part1.tex |
146 |
146 |
\pagebreak |
\pagebreak |
147 |
|
\input{part2} % вторая глава - в файле part2.tex |
|
|
147 |
|
\input{part4} % вторая глава - в файле part2.tex |
148 |
148 |
\pagebreak |
\pagebreak |
149 |
149 |
|
|
150 |
150 |
% если есть еще разделы - сохраните их в соответствующих файлах и раскомментируйте строки ниже, при необходимости добавьте еще |
% если есть еще разделы - сохраните их в соответствующих файлах и раскомментируйте строки ниже, при необходимости добавьте еще |
|
... |
... |
NumPy - Numerical Python |
160 |
160 |
\section*{\centering ЗАКЛЮЧЕНИЕ} |
\section*{\centering ЗАКЛЮЧЕНИЕ} |
161 |
161 |
\addcontentsline{toc}{section}{ЗАКЛЮЧЕНИЕ} |
\addcontentsline{toc}{section}{ЗАКЛЮЧЕНИЕ} |
162 |
162 |
|
|
163 |
|
В ходе проделанной работы был создан сценарий на языке Python для обработки и визуализации динамики температуры и осадков. Были выполнены следующие задачи: |
|
|
163 |
|
В ходе проделанной работы были созданы сценарии на языке Python для обработки и анализа метеоданных. Были выполнены следующие задачи: |
164 |
164 |
|
|
165 |
165 |
\begin{itemize} |
\begin{itemize} |
166 |
|
\item изучены методы декомпозиции временных рядов; |
|
|
166 |
|
\item разработан скрипт, строящий график размаха температур, высчитывающий межквартильный размах и выводящий значения декомпозиции метеопараметров в файл; |
167 |
167 |
|
|
168 |
|
\item изучены пакеты Python для работы с временными рядами; |
|
|
168 |
|
\item разработан скрипт, строящий графики трендов температур для нескольких метеостанций и выводящий значения в файл; |
169 |
169 |
|
|
170 |
|
\item подготовлены данные по динамике температуры и осадкам; |
|
171 |
|
|
|
172 |
|
\item разработан сценарий Python для декомпозиции и визуализации подготовленных данных. |
|
|
170 |
|
\item разработан скрипт, строящий графики случайной составляющей температур для нескольких метеостанций и выводящий значения в файл. |
173 |
171 |
\end{itemize} |
\end{itemize} |
174 |
172 |
|
|
175 |
173 |
% оформление библиографии - вариант с БД |
% оформление библиографии - вариант с БД |
|
... |
... |
from sys import argv |
208 |
206 |
from statsmodels.tsa.seasonal import seasonal_decompose |
from statsmodels.tsa.seasonal import seasonal_decompose |
209 |
207 |
from pandas.plotting import register_matplotlib_converters |
from pandas.plotting import register_matplotlib_converters |
210 |
208 |
|
|
211 |
|
script, data1, data2 = argv |
|
212 |
|
|
|
213 |
|
city1 = data1.replace(".txt", "") |
|
214 |
|
city2 = data2.replace(".txt", "") |
|
|
209 |
|
script, data_file = argv |
215 |
210 |
|
|
216 |
211 |
register_matplotlib_converters() |
register_matplotlib_converters() |
217 |
212 |
|
|
|
... |
... |
original_stdout = sys.stdout |
219 |
214 |
|
|
220 |
215 |
# Считывание и обработка датасетов. |
# Считывание и обработка датасетов. |
221 |
216 |
print("Считывание и обработка данных.") |
print("Считывание и обработка данных.") |
222 |
|
data1 = pd.read_csv(data1, sep=";", header=None) |
|
223 |
|
data1.columns = ["index", "year", "month", "day", "temp_quality", |
|
224 |
|
"temp_min", "temp_avg", "temp_max", "precipitation"] |
|
225 |
|
data2 = pd.read_csv(data2, sep=";", header=None) |
|
226 |
|
data2.columns = ["index", "year", "month", "day", "temp_quality", |
|
227 |
|
"temp_min", "temp_avg", "temp_max", "precipitation"] |
|
|
217 |
|
data1 = pd.read_csv(data_file, sep=";", header=None) |
|
218 |
|
data1.columns = ["index", "year", "month", "day", |
|
219 |
|
"temp_quality", "temp_min", "temp_avg", |
|
220 |
|
"temp_max", "precipitation"] |
228 |
221 |
df1 = pd.DataFrame({'year': data1["year"], |
df1 = pd.DataFrame({'year': data1["year"], |
229 |
222 |
'month': data1["month"], |
'month': data1["month"], |
230 |
223 |
'day': data1["day"]}) |
'day': data1["day"]}) |
231 |
224 |
df1["date"] = pd.to_datetime(df1) |
df1["date"] = pd.to_datetime(df1) |
232 |
|
df1["temp_avg"] = data1["temp_avg"] |
|
233 |
|
df1["precipitation"] = pd.to_numeric(data1["precipitation"], |
|
|
225 |
|
df1["temp_avg"] = pd.to_numeric(data1["temp_avg"], |
|
226 |
|
errors='coerce') |
|
227 |
|
df1["temp_min"] = pd.to_numeric(data1["temp_min"], |
234 |
228 |
errors='coerce') |
errors='coerce') |
235 |
|
df2 = pd.DataFrame({'year': data2["year"], |
|
236 |
|
'month': data2["month"], |
|
237 |
|
'day': data2["day"]}) |
|
238 |
|
df2["date"] = pd.to_datetime(df2) |
|
239 |
|
df2["temp_avg"] = data2["temp_avg"] |
|
240 |
|
df2["precipitation"] = pd.to_numeric(data2["precipitation"], |
|
|
229 |
|
df1["temp_max"] = pd.to_numeric(data1["temp_max"], |
241 |
230 |
errors='coerce') |
errors='coerce') |
|
231 |
|
df1["precipitation"] = pd.to_numeric(data1["precipitation"], |
|
232 |
|
errors='coerce') |
|
233 |
|
|
|
234 |
|
meteo_index = str(data1["index"].iloc[0]) |
242 |
235 |
|
|
243 |
236 |
# Стилизация графиков. |
# Стилизация графиков. |
244 |
237 |
sns.set_style("darkgrid") |
sns.set_style("darkgrid") |
|
... |
... |
plt.rc("lines", linewidth=3) |
251 |
244 |
if not os.path.exists("Result"): |
if not os.path.exists("Result"): |
252 |
245 |
os.makedirs("Result") |
os.makedirs("Result") |
253 |
246 |
|
|
254 |
|
# Построения графика среднегодовой температуры города 1. |
|
255 |
|
print("Построения графика среднегодовой температуры города " + |
|
256 |
|
city1 + ".") |
|
|
247 |
|
# Построения графика среднегодовой температуры. |
|
248 |
|
print("Построения графика среднегодовой температуры (" + |
|
249 |
|
+ meteo_index + ").") |
257 |
250 |
result1 = df1.groupby('year').mean() |
result1 = df1.groupby('year').mean() |
258 |
|
plt.plot(result1.index, result1['temp_avg']) |
|
259 |
|
plt.title("Среднегодовая температура (" + city1 + ")") |
|
|
251 |
|
plt.plot(result1.index, result1["temp_avg"]) |
|
252 |
|
plt.title("Среднегодовая температура (" + meteo_index + ")") |
260 |
253 |
plt.xlabel('Год') |
plt.xlabel('Год') |
261 |
254 |
plt.ylabel('Температура (цельсии)') |
plt.ylabel('Температура (цельсии)') |
262 |
255 |
z = np.polyfit(result1.index, result1['temp_avg'], 1) |
z = np.polyfit(result1.index, result1['temp_avg'], 1) |
263 |
256 |
p = np.poly1d(z) |
p = np.poly1d(z) |
264 |
257 |
plt.plot(result1.index, p(result1.index), "r--") |
plt.plot(result1.index, p(result1.index), "r--") |
265 |
|
plt.savefig('Result/' + city1 + '_Temperature_Plot.png') |
|
|
258 |
|
plt.savefig('Result/' + meteo_index + '_Temperature_Plot.png') |
266 |
259 |
plt.clf() |
plt.clf() |
267 |
260 |
|
|
268 |
|
# Построения графика количества осадков за год города 1. |
|
269 |
|
print("Построения графика количества осадков за год города " + |
|
270 |
|
city1 + ".") |
|
|
261 |
|
# Построения графика количества осадков за год. |
|
262 |
|
print("Построения графика количества осадков за год (" + |
|
263 |
|
+ meteo_index + ").") |
271 |
264 |
plt.plot(result1.index, result1['precipitation']) |
plt.plot(result1.index, result1['precipitation']) |
272 |
|
plt.title("Количество осадков за год (" + city1 + ")") |
|
|
265 |
|
plt.title("Количество осадков за год (" + meteo_index + ")") |
273 |
266 |
plt.xlabel('Год') |
plt.xlabel('Год') |
274 |
267 |
plt.ylabel('Количество осадков') |
plt.ylabel('Количество осадков') |
275 |
268 |
z = np.polyfit(result1.index, result1['precipitation'], 1) |
z = np.polyfit(result1.index, result1['precipitation'], 1) |
276 |
269 |
p = np.poly1d(z) |
p = np.poly1d(z) |
277 |
270 |
plt.plot(result1.index, p(result1.index), "r--") |
plt.plot(result1.index, p(result1.index), "r--") |
278 |
|
plt.savefig('Result/' + city1 + '_Precipitations_Plot.png') |
|
|
271 |
|
plt.savefig('Result/' + meteo_index + '_Precipitations_Plot.png') |
279 |
272 |
plt.clf() |
plt.clf() |
280 |
273 |
|
|
281 |
|
# Построения графика среднегодовой температуры города 2. |
|
282 |
|
print("Построения графика среднегодовой температуры города " + |
|
283 |
|
city2 + ".") |
|
284 |
|
result2 = df2.groupby('year').mean() |
|
285 |
|
plt.plot(result2.index, result2['temp_avg']) |
|
286 |
|
plt.title("Среднегодовая температура (" + city2 + ")") |
|
287 |
|
plt.xlabel('Год') |
|
|
274 |
|
# Построения диаграммы размаха среднегодовой температуры. |
|
275 |
|
print("Построения диаграммы размаха среднегодовой температуры (" + |
|
276 |
|
+ meteo_index + ").") |
|
277 |
|
sns.boxplot(data=df1, x='month', y='temp_avg') |
|
278 |
|
plt.xlabel('Месяц') |
288 |
279 |
plt.ylabel('Температура (цельсии)') |
plt.ylabel('Температура (цельсии)') |
289 |
|
z = np.polyfit(result2.index, result2['temp_avg'], 1) |
|
290 |
|
p = np.poly1d(z) |
|
291 |
|
plt.plot(result2.index, p(result2.index), "r--") |
|
292 |
|
plt.savefig('Result/' + city2 + '_Temperature_Plot.png') |
|
|
280 |
|
plt.title('Температура (' + meteo_index + ')') |
|
281 |
|
plt.savefig('Result/' + meteo_index + '_Temperature_Boxplot.png') |
293 |
282 |
plt.clf() |
plt.clf() |
294 |
283 |
|
|
295 |
|
# Построения графика количества осадков за год города 2. |
|
296 |
|
print("Построения графика количества осадков за год города " |
|
297 |
|
+ city2 + ".") |
|
298 |
|
plt.plot(result2.index, result2['precipitation']) |
|
299 |
|
plt.title("Количество осадков за год (" + city2 + ")") |
|
300 |
|
plt.xlabel('Год') |
|
301 |
|
plt.ylabel('Количество осадков') |
|
302 |
|
z = np.polyfit(result2.index, result2['precipitation'], 1) |
|
303 |
|
p = np.poly1d(z) |
|
304 |
|
plt.plot(result2.index, p(result2.index), "r--") |
|
305 |
|
plt.savefig('Result/' + city2 + '_Precipitations_Plot.png') |
|
|
284 |
|
# Декомпозиция данных по температуре. |
|
285 |
|
print("Декомпозиция данных по температуре (" + meteo_index + ").") |
|
286 |
|
result = seasonal_decompose(result1['temp_avg'], model='additive', |
|
287 |
|
period=12) |
|
288 |
|
result.plot() |
|
289 |
|
plt.savefig('Result/' + meteo_index + |
|
290 |
|
+ '_Temperature_Decomposition.png') |
306 |
291 |
plt.clf() |
plt.clf() |
307 |
|
|
|
308 |
|
#Построения графика корреляции среднегодовой температуры двух городов |
|
309 |
|
print("Построения графика корреляции среднегодовой температуры" + |
|
310 |
|
" двух городов.") |
|
311 |
|
plt.plot(result1.index, result1['temp_avg'], |
|
312 |
|
label="Среднегодовая температура в городе " + city1) |
|
313 |
|
plt.plot(result2.index, result2['temp_avg'], |
|
314 |
|
label="Среднегодовая температура в городе " + city2) |
|
315 |
|
plt.title("Среднегодовая температура в городах " + city1 + " и " + |
|
316 |
|
city2) |
|
|
292 |
|
numpy_array = result.trend.to_numpy() |
|
293 |
|
np.savetxt("Result/" + meteo_index + "_Temperature_Trend.txt", |
|
294 |
|
numpy_array, fmt="%f") |
|
295 |
|
numpy_array = result.seasonal.to_numpy() |
|
296 |
|
np.savetxt("Result/" + meteo_index + "_Temperature_Seasonal.txt", |
|
297 |
|
numpy_array, fmt="%f") |
|
298 |
|
numpy_array = result.resid.to_numpy() |
|
299 |
|
np.savetxt("Result/" + meteo_index + "_Temperature_Residual.txt", |
|
300 |
|
numpy_array, fmt="%f") |
|
301 |
|
|
|
302 |
|
# Декомпозиция данных по осадкам. |
|
303 |
|
print("Декомпозиция данных по осадкам (" + meteo_index + ").") |
|
304 |
|
result = seasonal_decompose(result1['precipitation'], |
|
305 |
|
model='additive', period=12) |
|
306 |
|
result.plot() |
|
307 |
|
plt.savefig('Result/' + meteo_index + |
|
308 |
|
+ '_Precipitations_Decomposition.png') |
|
309 |
|
plt.clf() |
|
310 |
|
numpy_array = result.trend.to_numpy() |
|
311 |
|
np.savetxt("Result/" + meteo_index + "_Precipitations_Trend.txt", |
|
312 |
|
numpy_array, fmt="%f") |
|
313 |
|
numpy_array = result.seasonal.to_numpy() |
|
314 |
|
np.savetxt("Result/" + meteo_index + "_Precipitations_Seasonal.txt", |
|
315 |
|
numpy_array, fmt="%f") |
|
316 |
|
numpy_array = result.resid.to_numpy() |
|
317 |
|
np.savetxt("Result/" + meteo_index + "_Precipitations_Residual.txt", |
|
318 |
|
numpy_array, fmt="%f") |
|
319 |
|
|
|
320 |
|
# IQR |
|
321 |
|
q75, q25 = np.percentile(result1['temp_avg'], [75, 25]) |
|
322 |
|
iqr = q75 - q25 |
|
323 |
|
with open('Result/' + meteo_index + '_Temperature_IQR.txt', 'w') |
|
324 |
|
as f: |
|
325 |
|
f.write('IQR = ' + str(iqr)) |
|
326 |
|
q75, q25 = np.percentile(result1['precipitation'], [75, 25]) |
|
327 |
|
iqr = q75 - q25 |
|
328 |
|
with open('Result/' + meteo_index + '_Precipitations_IQR.txt', 'w') |
|
329 |
|
as f: |
|
330 |
|
f.write('IQR = ' + str(iqr)) |
|
331 |
|
|
|
332 |
|
# Построение графика размаха температур. |
|
333 |
|
print("Построение графика размаха температур (" + meteo_index + ").") |
|
334 |
|
plt.plot(result1.index, result1['temp_max'] - |
|
335 |
|
- result1['temp_min']) |
|
336 |
|
plt.title("Размах температур (" + meteo_index + ")") |
317 |
337 |
plt.xlabel('Год') |
plt.xlabel('Год') |
318 |
338 |
plt.ylabel('Температура (цельсии)') |
plt.ylabel('Температура (цельсии)') |
319 |
|
plt.legend() |
|
320 |
|
plt.savefig('Result/Correlation_Temperature_Plot.png') |
|
321 |
|
print("Расчёт корреляции среднегодовой температуры двух городов.") |
|
322 |
|
corr1 = np.corrcoef(result1['temp_avg'], result2['temp_avg']) |
|
323 |
|
with open('Result/Temperature_Correlation.txt', 'w') as f: |
|
324 |
|
sys.stdout = f |
|
325 |
|
print('Матрица корреляции температур:\n') |
|
326 |
|
print(corr1) |
|
327 |
|
sys.stdout = original_stdout |
|
|
339 |
|
z = np.polyfit(result1.index, result1['temp_max'] - |
|
340 |
|
- result1['temp_min'], 1) |
|
341 |
|
p = np.poly1d(z) |
|
342 |
|
plt.plot(result1.index, p(result1.index), "r--") |
|
343 |
|
plt.savefig('Result/' + meteo_index + '_TemperatureRange_Plot.png') |
328 |
344 |
plt.clf() |
plt.clf() |
329 |
345 |
|
|
330 |
|
#Построения графика корреляции количества осадков за год двух городов |
|
331 |
|
print("Построения графика корреляции количества осадков за год" + |
|
332 |
|
" двух городов.") |
|
333 |
|
plt.plot(result1.index, result1['precipitation'], |
|
334 |
|
label="Среднегодовые осадки в городе " + city1) |
|
335 |
|
plt.plot(result2.index, result2['precipitation'], |
|
336 |
|
label="Среднегодовые осадки в городе " + city2) |
|
337 |
|
plt.title("Среднегодовые осадки в городах " + city1 + " и " + city2) |
|
338 |
|
plt.xlabel('Год') |
|
339 |
|
plt.ylabel('Количество осадков') |
|
|
346 |
|
print("\nРабота успешно завершена!") |
|
347 |
|
\end{MyCode} |
|
348 |
|
\begin{Program} |
|
349 |
|
\caption{Код реализации скрипта DecomposeToFile.py}\label{app1} |
|
350 |
|
\end{Program} |
|
351 |
|
|
|
352 |
|
\begin{MyCode} |
|
353 |
|
import os |
|
354 |
|
import sys |
|
355 |
|
import pandas as pd |
|
356 |
|
import matplotlib.pyplot as plt |
|
357 |
|
import seaborn as sns |
|
358 |
|
from sys import argv |
|
359 |
|
from statsmodels.tsa.seasonal import seasonal_decompose |
|
360 |
|
from pandas.plotting import register_matplotlib_converters |
|
361 |
|
|
|
362 |
|
script, data_file = argv |
|
363 |
|
|
|
364 |
|
register_matplotlib_converters() |
|
365 |
|
|
|
366 |
|
original_stdout = sys.stdout |
|
367 |
|
|
|
368 |
|
if not os.path.exists("Result"): |
|
369 |
|
os.makedirs("Result") |
|
370 |
|
|
|
371 |
|
if os.path.exists("Result/Temperature_Trend.txt"): |
|
372 |
|
os.remove("Result/Temperature_Trend.txt") |
|
373 |
|
|
|
374 |
|
# Стилизация графиков. |
|
375 |
|
sns.set_style("darkgrid") |
|
376 |
|
plt.rc("figure", figsize=(12, 9)) |
|
377 |
|
plt.rc("font", size=13) |
|
378 |
|
plt.rc("lines", markersize=5) |
|
379 |
|
plt.rc("lines", linewidth=3) |
|
380 |
|
plt.xlabel("Дата") |
|
381 |
|
plt.ylabel("Температура") |
|
382 |
|
plt.title("График трендов температур") |
|
383 |
|
|
|
384 |
|
# Считывание и обработка данных. |
|
385 |
|
print("Считывание и обработка данных.") |
|
386 |
|
data = pd.read_csv(data_file, dtype=object, sep=";", header=None) |
|
387 |
|
data.columns = ["index", "year", "month", "day", "temp_quality", |
|
388 |
|
"temp_min", "temp_avg", "temp_max", "precipitation"] |
|
389 |
|
data.loc[data['temp_avg'] == '', 'temp_avg'] = 0.0 |
|
390 |
|
df = pd.DataFrame({'year': data["year"], |
|
391 |
|
'month': data["month"], |
|
392 |
|
'day': data["day"]}) |
|
393 |
|
df["date"] = pd.to_datetime(df) |
|
394 |
|
df["temp_avg"] = pd.to_numeric(data["temp_avg"], |
|
395 |
|
errors='coerce') |
|
396 |
|
df["precipitation"] = pd.to_numeric(data["precipitation"], |
|
397 |
|
errors='coerce') |
|
398 |
|
df["index"] = data["index"] |
|
399 |
|
df['temp_avg'] = df['temp_avg'].interpolate(method='slinear') \ |
|
400 |
|
.interpolate(method='linear') |
|
401 |
|
grouped = df.groupby('index') |
|
402 |
|
index_list = df['index'].unique().tolist() |
|
403 |
|
|
|
404 |
|
for x in index_list: |
|
405 |
|
elem = grouped.get_group(x).groupby("year").mean() |
|
406 |
|
dec = seasonal_decompose(elem["temp_avg"], model='additive', |
|
407 |
|
period=12) |
|
408 |
|
plt.plot(elem.index.to_numpy(), dec.trend.to_numpy(), label=x) |
|
409 |
|
a = {'index': x, |
|
410 |
|
'year': elem.index, |
|
411 |
|
'trend': dec.trend.to_numpy() |
|
412 |
|
} |
|
413 |
|
b = pd.DataFrame(a) |
|
414 |
|
b.to_csv("Result/Temperature_Trend.txt", header=None, |
|
415 |
|
index=None, sep=';', mode='a') |
|
416 |
|
|
340 |
417 |
plt.legend() |
plt.legend() |
341 |
|
plt.savefig('Result/Correlation_Precipitations_Plot.png') |
|
342 |
|
print("Расчёт корреляции количества осадков за год двух городов.") |
|
343 |
|
corr2 = np.corrcoef(result1['precipitation'], |
|
344 |
|
result2['precipitation']) |
|
345 |
|
with open('Result/Precipitations_Correlation.txt', 'w') as f: |
|
346 |
|
sys.stdout = f |
|
347 |
|
print('Матрица корреляции осадков:\n') |
|
348 |
|
print(corr2) |
|
349 |
|
sys.stdout = original_stdout |
|
350 |
|
plt.clf() |
|
|
418 |
|
plt.savefig('Result/Temperature_Trends_Decomposition.png') |
351 |
419 |
|
|
352 |
|
# Построения диаграммы размаха среднегодовой температуры города 1. |
|
353 |
|
print("Построения диаграммы размаха среднегодовой температуры города " |
|
354 |
|
+ city1 + ".") |
|
355 |
|
sns.boxplot(data=df1, x='month', y='temp_avg') |
|
356 |
|
plt.xlabel('Месяц') |
|
357 |
|
plt.ylabel('Температура (цельсии)') |
|
358 |
|
plt.title('Температура в городе ' + city1) |
|
359 |
|
plt.savefig('Result/' + city1 + '_Temperature_Boxplot.png') |
|
360 |
|
plt.clf() |
|
|
420 |
|
print("Результат сохранён в папку Result.") |
|
421 |
|
\end{MyCode} |
|
422 |
|
\begin{Program} |
|
423 |
|
\caption{Код реализации скрипта TrendCalc.py}\label{app1} |
|
424 |
|
\end{Program} |
361 |
425 |
|
|
362 |
|
# Построения диаграммы размаха среднегодовой температуры города 2. |
|
363 |
|
print("Построения диаграммы размаха среднегодовой температуры города " |
|
364 |
|
+ city2 + ".") |
|
365 |
|
sns.boxplot(data=df2, x='month', y='temp_avg') |
|
366 |
|
plt.xlabel('Месяц') |
|
367 |
|
plt.ylabel('Температура (цельсии)') |
|
368 |
|
plt.title('Температура в городе ' + city2) |
|
369 |
|
plt.savefig('Result/' + city2 + '_Temperature_Boxplot.png') |
|
370 |
|
plt.clf() |
|
|
426 |
|
\begin{MyCode} |
|
427 |
|
import os |
|
428 |
|
import sys |
|
429 |
|
import pandas as pd |
|
430 |
|
import matplotlib.pyplot as plt |
|
431 |
|
import seaborn as sns |
|
432 |
|
from sys import argv |
|
433 |
|
from statsmodels.tsa.seasonal import seasonal_decompose |
|
434 |
|
from pandas.plotting import register_matplotlib_converters |
371 |
435 |
|
|
372 |
|
# Декомпозиция данных по температуре города 1. |
|
373 |
|
print("Декомпозиция данных по температуре города " + city1 + ".") |
|
374 |
|
result = seasonal_decompose(result1['temp_avg'], model='additive', |
|
375 |
|
period=12) |
|
376 |
|
result.plot() |
|
377 |
|
plt.savefig('Result/' + city1 + '_Temperature_Decomposition.png') |
|
378 |
|
plt.clf() |
|
|
436 |
|
script, data_file = argv |
379 |
437 |
|
|
380 |
|
# Декомпозиция данных по осадкам города 1. |
|
381 |
|
print("Декомпозиция данных по осадкам города " + city1 + ".") |
|
382 |
|
result = seasonal_decompose(result1['precipitation'], |
|
383 |
|
model='additive', period=12) |
|
384 |
|
result.plot() |
|
385 |
|
plt.savefig('Result/' + city1 + '_Precipitations_Decomposition.png') |
|
386 |
|
plt.clf() |
|
|
438 |
|
register_matplotlib_converters() |
387 |
439 |
|
|
388 |
|
# Декомпозиция данных по температуре города 2. |
|
389 |
|
print("Декомпозиция данных по температуре города " + city2 + ".") |
|
390 |
|
result = seasonal_decompose(result2['temp_avg'], model='additive', |
|
391 |
|
period=12) |
|
392 |
|
result.plot() |
|
393 |
|
plt.savefig('Result/' + city2 + '_Temperature_Decomposition.png') |
|
394 |
|
plt.clf() |
|
|
440 |
|
original_stdout = sys.stdout |
395 |
441 |
|
|
396 |
|
# Декомпозиция данных по осадкам города 2. |
|
397 |
|
print("Декомпозиция данных по осадкам города " + city2 + ".") |
|
398 |
|
result = seasonal_decompose(result2['precipitation'], |
|
399 |
|
model='additive', period=12) |
|
400 |
|
result.plot() |
|
401 |
|
plt.savefig('Result/' + city2 + '_Precipitations_Decomposition.png') |
|
402 |
|
plt.clf() |
|
|
442 |
|
if not os.path.exists("Result"): |
|
443 |
|
os.makedirs("Result") |
403 |
444 |
|
|
404 |
|
print("\nРабота успешно завершена!") |
|
|
445 |
|
if os.path.exists("Result/Temperature_Residual.txt"): |
|
446 |
|
os.remove("Result/Temperature_Residual.txt") |
|
447 |
|
|
|
448 |
|
# Стилизация графиков. |
|
449 |
|
sns.set_style("darkgrid") |
|
450 |
|
plt.rc("figure", figsize=(12, 9)) |
|
451 |
|
plt.rc("font", size=13) |
|
452 |
|
plt.rc("lines", markersize=5) |
|
453 |
|
plt.rc("lines", linewidth=3) |
|
454 |
|
plt.xlabel("Дата") |
|
455 |
|
plt.ylabel("Температура") |
|
456 |
|
plt.title("График случайного значения декомпозиции температур") |
|
457 |
|
|
|
458 |
|
# Считывание и обработка данных. |
|
459 |
|
print("Считывание и обработка данных.") |
|
460 |
|
data = pd.read_csv(data_file, dtype=object, sep=";", header=None) |
|
461 |
|
data.columns = ["index", "year", "month", "day", "temp_quality", |
|
462 |
|
"temp_min", "temp_avg", "temp_max", "precipitation"] |
|
463 |
|
data.loc[data['temp_avg'] == '', 'temp_avg'] = 0.0 |
|
464 |
|
df = pd.DataFrame({'year': data["year"], |
|
465 |
|
'month': data["month"], |
|
466 |
|
'day': data["day"]}) |
|
467 |
|
df["date"] = pd.to_datetime(df) |
|
468 |
|
df["temp_avg"] = pd.to_numeric(data["temp_avg"], |
|
469 |
|
errors='coerce') |
|
470 |
|
df["precipitation"] = pd.to_numeric(data["precipitation"], |
|
471 |
|
errors='coerce') |
|
472 |
|
df["index"] = data["index"] |
|
473 |
|
df['temp_avg'] = df['temp_avg'].interpolate(method='slinear') \ |
|
474 |
|
.interpolate(method='linear') |
|
475 |
|
grouped = df.groupby('index') |
|
476 |
|
index_list = df['index'].unique().tolist() |
|
477 |
|
|
|
478 |
|
for x in index_list: |
|
479 |
|
elem = grouped.get_group(x).groupby("year").mean() |
|
480 |
|
dec = seasonal_decompose(elem["temp_avg"], model='additive', |
|
481 |
|
period=12) |
|
482 |
|
plt.plot(elem.index.to_numpy(), dec.resid.to_numpy(), label=x) |
|
483 |
|
a = {'index': x, |
|
484 |
|
'year': elem.index, |
|
485 |
|
'residual': dec.resid.to_numpy() |
|
486 |
|
} |
|
487 |
|
b = pd.DataFrame(a) |
|
488 |
|
b.to_csv("Result/Temperature_Residual.txt", header=None, |
|
489 |
|
index=None, sep=';', mode='a') |
|
490 |
|
|
|
491 |
|
plt.legend() |
|
492 |
|
plt.savefig('Result/Temperature_Residual_Decomposition.png') |
|
493 |
|
|
|
494 |
|
print("Результат сохранён в папку Result.") |
405 |
495 |
\end{MyCode} |
\end{MyCode} |
406 |
496 |
\begin{Program} |
\begin{Program} |
407 |
|
\caption{Код реализации скрипта}\label{app1} |
|
|
497 |
|
\caption{Код реализации скрипта ResidCalc.py}\label{app1} |
408 |
498 |
\end{Program} |
\end{Program} |
409 |
499 |
\end{appendices} |
\end{appendices} |
410 |
500 |
|
|
File part4.tex added (mode: 100644) (index 0000000..066b6d5) |
|
1 |
|
% вторая часть |
|
2 |
|
|
|
3 |
|
\section{Демонстрация работы скриптов} |
|
4 |
|
|
|
5 |
|
\subsection{Обзор скриптов} |
|
6 |
|
|
|
7 |
|
По завершении работы было разработано три скрипта, выполняющих разные задачи: |
|
8 |
|
\begin{itemize} |
|
9 |
|
\item DecomposeToFile.py - строит для одной точки наблюдения графики среднегодовой температуры и количества осадков за год, диаграмму размаха среднегодовой температуры, графики декомпозиции данных по температуре и осадкам, график размаха температур, считает межквартильный размах. Результаты декомпозиции выводит в отдельные файлы; |
|
10 |
|
|
|
11 |
|
\item TrendCalc.py - строит графики трендовых составляющих для нескольких точек наблюдения и выводит результат декомпозиции в файл; |
|
12 |
|
|
|
13 |
|
\item ResidCalc.py - строит графики случайных составляющих для нескольких точек наблюдения и выводит результат декомпозиции в файл. |
|
14 |
|
\end{itemize} |
|
15 |
|
Все результаты вычислений сохраняются в папку Result. |
|
16 |
|
|
|
17 |
|
\subsection{Получение данных} |
|
18 |
|
|
|
19 |
|
Данные по температуре и осадкам были взяты с сайта \verb|aisori-m.meteo.ru|. Пример запроса в базу данных приведён на рис.~\ref{fig:1}. |
|
20 |
|
|
|
21 |
|
\begin{figure}[H] |
|
22 |
|
\centering |
|
23 |
|
\includegraphics[width=0.75\linewidth]{pics/1} |
|
24 |
|
\caption{Пример запроса в базу данных} |
|
25 |
|
\label{fig:1} |
|
26 |
|
\end{figure} |
|
27 |
|
|
|
28 |
|
Получены датасеты с данными о погоде с 1950 по 2020 год с нескольких западных, северо-западных и сибирских российских метеостанций и станции Москва (ВДНХ) с индексом 27459 со следующими столбцами: |
|
29 |
|
\begin{itemize} |
|
30 |
|
\item индекс ВМО; |
|
31 |
|
|
|
32 |
|
\item год; |
|
33 |
|
|
|
34 |
|
\item месяц; |
|
35 |
|
|
|
36 |
|
\item день; |
|
37 |
|
|
|
38 |
|
\item общий признак качества температур; |
|
39 |
|
|
|
40 |
|
\item минимальная температура воздуха; |
|
41 |
|
|
|
42 |
|
\item средняя температура воздуха; |
|
43 |
|
|
|
44 |
|
\item максимальная температура воздуха; |
|
45 |
|
|
|
46 |
|
\item количество осадков. |
|
47 |
|
\end{itemize} |
|
48 |
|
Датасеты содержат точку с запятой в качестве разделителя. |
|
49 |
|
|
|
50 |
|
\begin{figure}[H] |
|
51 |
|
\centering |
|
52 |
|
\includegraphics[width=0.50\linewidth]{pics/2} |
|
53 |
|
\caption{Результат запроса в БД} |
|
54 |
|
\label{fig:2} |
|
55 |
|
\end{figure} |
|
56 |
|
|
|
57 |
|
Для запада России были взяты следующие метеостанции: |
|
58 |
|
\begin{itemize} |
|
59 |
|
\item 26298 Бологое; |
|
60 |
|
|
|
61 |
|
\item 26898 Брянск; |
|
62 |
|
|
|
63 |
|
\item 26477 Великие Луки; |
|
64 |
|
|
|
65 |
|
\item 34123 Воронеж; |
|
66 |
|
|
|
67 |
|
\item 27625 Коломна; |
|
68 |
|
|
|
69 |
|
\item 27333 Кострома; |
|
70 |
|
|
|
71 |
|
\item 27612 Москва, ВДНХ; |
|
72 |
|
|
|
73 |
|
\item 27962 Пенза; |
|
74 |
|
|
|
75 |
|
\item 26258 Псков; |
|
76 |
|
|
|
77 |
|
\item 27730 Рязань; |
|
78 |
|
|
|
79 |
|
\item 26781 Смоленск; |
|
80 |
|
|
|
81 |
|
\item 26275 Старая Русса; |
|
82 |
|
|
|
83 |
|
\item 27707 Сухиничи; |
|
84 |
|
|
|
85 |
|
\item 27947 Тамбов; |
|
86 |
|
|
|
87 |
|
\item 26997 Трубчевск. |
|
88 |
|
\end{itemize} |
|
89 |
|
|
|
90 |
|
Для северо-запада России: |
|
91 |
|
\begin{itemize} |
|
92 |
|
\item 22550 Архангельск; |
|
93 |
|
|
|
94 |
|
\item 27037 Вологда, Прилуки; |
|
95 |
|
|
|
96 |
|
\item 22887 Котлас; |
|
97 |
|
|
|
98 |
|
\item 22113 Мурманск; |
|
99 |
|
|
|
100 |
|
\item 22820 Петрозаводск; |
|
101 |
|
|
|
102 |
|
\item 26094 Тихвин. |
|
103 |
|
\end{itemize} |
|
104 |
|
|
|
105 |
|
Для Сибири: |
|
106 |
|
\begin{itemize} |
|
107 |
|
\item 29838 Барнаул; |
|
108 |
|
|
|
109 |
|
\item 29939 Бийск-Зональная; |
|
110 |
|
|
|
111 |
|
\item 30710 Иркутск; |
|
112 |
|
|
|
113 |
|
\item 29645 Кемерово; |
|
114 |
|
|
|
115 |
|
\item 29570 Красноярск; |
|
116 |
|
|
|
117 |
|
\item 28698 Омск; |
|
118 |
|
|
|
119 |
|
\item 29430 Томск; |
|
120 |
|
|
|
121 |
|
\item 30823 Улан-Удэ; |
|
122 |
|
|
|
123 |
|
\item 30758 Чита. |
|
124 |
|
\end{itemize} |
|
125 |
|
|
|
126 |
|
\subsection{Запуск скрипта DecomposeToFile.py} |
|
127 |
|
|
|
128 |
|
Перед запуском скрипта его необходимо переместить в папку с метеоданными. |
|
129 |
|
|
|
130 |
|
Скрипт запускается через командную строку Windows. |
|
131 |
|
|
|
132 |
|
\begin{figure}[H] |
|
133 |
|
\centering |
|
134 |
|
\includegraphics[width=0.75\linewidth]{pics/28} |
|
135 |
|
\caption{Запуск скрипта DecomposeToFile.py} |
|
136 |
|
\label{fig:3} |
|
137 |
|
\end{figure} |
|
138 |
|
|
|
139 |
|
В командной строке необходимо перейти по пути, где лежит скрипт, с помощью команды cd. После этого запустить скрипт с одним параметром, представляющим из себя название файла с метеоданными. |
|
140 |
|
|
|
141 |
|
После завершения работы скрипта, весь результат сохраняется в папке Result. |
|
142 |
|
|
|
143 |
|
\subsection{Результат работы скрипта DecomposeToFile.py} |
|
144 |
|
|
|
145 |
|
После завершения работы скрипта построены следующие графики: |
|
146 |
|
|
|
147 |
|
\begin{itemize} |
|
148 |
|
\item графики среднегодовых температур и осадков в точке наблюдения; |
|
149 |
|
|
|
150 |
|
\begin{figure}[H] |
|
151 |
|
\centering |
|
152 |
|
\includegraphics[width=0.75\linewidth]{pics/29} |
|
153 |
|
\caption{График среднегодовой температуры в Москве} |
|
154 |
|
\label{fig:4} |
|
155 |
|
\end{figure} |
|
156 |
|
|
|
157 |
|
\begin{figure}[H] |
|
158 |
|
\centering |
|
159 |
|
\includegraphics[width=0.75\linewidth]{pics/30} |
|
160 |
|
\caption{График среднегодовых осадков в Москве} |
|
161 |
|
\label{fig:5} |
|
162 |
|
\end{figure} |
|
163 |
|
|
|
164 |
|
\item коробочная диаграмма по температуре; |
|
165 |
|
|
|
166 |
|
\begin{figure}[H] |
|
167 |
|
\centering |
|
168 |
|
\includegraphics[width=0.75\linewidth]{pics/31} |
|
169 |
|
\caption{Коробочная диаграмма температуры в Москве} |
|
170 |
|
\label{fig:6} |
|
171 |
|
\end{figure} |
|
172 |
|
|
|
173 |
|
\item графики декомпозиции данных по температуре и осадкам; |
|
174 |
|
|
|
175 |
|
\begin{figure}[H] |
|
176 |
|
\centering |
|
177 |
|
\includegraphics[width=0.75\linewidth]{pics/32} |
|
178 |
|
\caption{Декомпозиция данных по температуре в Москве} |
|
179 |
|
\label{fig:7} |
|
180 |
|
\end{figure} |
|
181 |
|
|
|
182 |
|
\begin{figure}[H] |
|
183 |
|
\centering |
|
184 |
|
\includegraphics[width=0.75\linewidth]{pics/33} |
|
185 |
|
\caption{Декомпозиция данных по осадкам в Москве} |
|
186 |
|
\label{fig:8} |
|
187 |
|
\end{figure} |
|
188 |
|
|
|
189 |
|
\item график размаха температур. |
|
190 |
|
|
|
191 |
|
\begin{figure}[H] |
|
192 |
|
\centering |
|
193 |
|
\includegraphics[width=0.75\linewidth]{pics/34} |
|
194 |
|
\caption{График размаха температур} |
|
195 |
|
\label{fig:9} |
|
196 |
|
\end{figure} |
|
197 |
|
|
|
198 |
|
\end{itemize} |
|
199 |
|
|
|
200 |
|
Так же в папку Result были сохранены следующие текстовые документы: |
|
201 |
|
\begin{itemize} |
|
202 |
|
\item результаты декомпозиции данных по температуре и осадкам; |
|
203 |
|
|
|
204 |
|
\item результаты вычисления межквартильного размаха по температуре и осадкам. |
|
205 |
|
\end{itemize} |
|
206 |
|
|
|
207 |
|
\subsection{Запуск скриптов TrendCalc.py и ResidCalc.py} |
|
208 |
|
|
|
209 |
|
Перед запуском скриптов их необходимо переместить в папку с метеоданными. |
|
210 |
|
|
|
211 |
|
Скрипты запускаются через командную строку Windows. |
|
212 |
|
|
|
213 |
|
\begin{figure}[H] |
|
214 |
|
\centering |
|
215 |
|
\includegraphics[width=0.75\linewidth]{pics/35} |
|
216 |
|
\caption{Запуск скриптов TrendCalc.py и ResidCalc.py} |
|
217 |
|
\label{fig:10} |
|
218 |
|
\end{figure} |
|
219 |
|
|
|
220 |
|
В командной строке необходимо перейти по пути, где лежат скрипты, с помощью команды cd. После этого запустить каждый скрипт с одним параметром, представляющим из себя название файла с метеоданными. |
|
221 |
|
|
|
222 |
|
После завершения работы скриптов, весь результат сохраняется в папке Result. |
|
223 |
|
|
|
224 |
|
\subsection{Результат работы скриптов TrendCalc.py и ResidCalc.py} |
|
225 |
|
|
|
226 |
|
После завершения работы скрипта построены следующие графики: |
|
227 |
|
\begin{itemize} |
|
228 |
|
\item графики трендов температур для нескольких метеостанций; |
|
229 |
|
|
|
230 |
|
\begin{figure}[H] |
|
231 |
|
\centering |
|
232 |
|
\includegraphics[width=0.75\linewidth]{pics/36} |
|
233 |
|
\caption{График трендов температур для западных метеостанций} |
|
234 |
|
\label{fig:11} |
|
235 |
|
\end{figure} |
|
236 |
|
|
|
237 |
|
\begin{figure}[H] |
|
238 |
|
\centering |
|
239 |
|
\includegraphics[width=0.75\linewidth]{pics/37} |
|
240 |
|
\caption{График трендов температур для северо-западных метеостанций} |
|
241 |
|
\label{fig:12} |
|
242 |
|
\end{figure} |
|
243 |
|
|
|
244 |
|
\begin{figure}[H] |
|
245 |
|
\centering |
|
246 |
|
\includegraphics[width=0.75\linewidth]{pics/38} |
|
247 |
|
\caption{График трендов температур для сибирских метеостанций} |
|
248 |
|
\label{fig:13} |
|
249 |
|
\end{figure} |
|
250 |
|
|
|
251 |
|
\item графики случайной составляющей температур для нескольких метеостанций. |
|
252 |
|
|
|
253 |
|
\begin{figure}[H] |
|
254 |
|
\centering |
|
255 |
|
\includegraphics[width=0.75\linewidth]{pics/39} |
|
256 |
|
\caption{График случайной составляющей температур для западных метеостанций} |
|
257 |
|
\label{fig:14} |
|
258 |
|
\end{figure} |
|
259 |
|
|
|
260 |
|
\begin{figure}[H] |
|
261 |
|
\centering |
|
262 |
|
\includegraphics[width=0.75\linewidth]{pics/40} |
|
263 |
|
\caption{График случайной составляющей температур для северо-западных метеостанций} |
|
264 |
|
\label{fig:15} |
|
265 |
|
\end{figure} |
|
266 |
|
|
|
267 |
|
\begin{figure}[H] |
|
268 |
|
\centering |
|
269 |
|
\includegraphics[width=0.75\linewidth]{pics/41} |
|
270 |
|
\caption{График случайной составляющей температур для сибирских метеостанций} |
|
271 |
|
\label{fig:16} |
|
272 |
|
\end{figure} |
|
273 |
|
|
|
274 |
|
\end{itemize} |
|
275 |
|
|
|
276 |
|
Так же в папку Result были сохранены следующие текстовые документы: |
|
277 |
|
\begin{itemize} |
|
278 |
|
\item данные по трендовой состовляющей температуры нескольких метеостанций; |
|
279 |
|
|
|
280 |
|
\item данные по случайной состовляющей температуры нескольких метеостанций. |
|
281 |
|
\end{itemize} |
|
282 |
|
|