# Подгружаем необходимые библиотеки

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
russia_reg = pd.read_csv('/kaggle/input/russia-regions-in-sber-covid-competition/russia_regions.csv')
"""
# Часть 1. Построение графиков. Динамика развития (заболеваемость) COVID-19 в трёх регионах России.
"""
# Отдельно сохраняем данные о заболеваемости в Москве и Московской области, Петербурге и Ленинградской области, Новосибирской области

russia_cases = pd.read_csv('/kaggle/input/covid19-russia-regions-cases/covid19-russia-cases-scrf.csv')
moscow_cases = russia_cases.loc[(russia_cases['Region/City'] == 'Москва') | (russia_cases['Region/City'] == 'Московская область')]
spb_cases = russia_cases.loc[(russia_cases['Region/City'] == 'Санкт-Петербург') | (russia_cases['Region/City'] == 'Ленинградская область')]
nsk_cases = russia_cases.loc[russia_cases['Region/City'] == 'Новосибирская область']
# Группируем данные по дате

moscow_cases = moscow_cases.groupby('Date').sum()
spb_cases = spb_cases.groupby('Date').sum()
nsk_cases = nsk_cases.groupby('Date').sum()
moscow_cases
spb_cases
nsk_cases
# Удаляем лишние столбцы

moscow_cases.drop(['Region_ID', 'Day-Confirmed', 'Day-Deaths', 'Day-Recovered', 'Deaths', 'Recovered'], axis=1, inplace=True)
spb_cases.drop(['Region_ID', 'Day-Confirmed', 'Day-Deaths', 'Day-Recovered', 'Deaths', 'Recovered'], axis=1, inplace=True)
nsk_cases.drop(['Region_ID', 'Day-Confirmed', 'Day-Deaths', 'Day-Recovered', 'Deaths', 'Recovered'], axis=1, inplace=True)
# График заболеваемости в регионах (Количество подтвержденных случаев - Дата)

fig, ax = plt.subplots(figsize=(15,10))
plt.plot(moscow_cases['Confirmed'], 'ro-', label = 'Moscow')
plt.plot(spb_cases['Confirmed'], 'go-', label = 'Saint-Petersburg')
plt.plot(nsk_cases['Confirmed'], 'bo-', label = 'Novosibirsk')
plt.ylabel('Confirmed')
plt.xlabel('Date')
plt.grid()
plt.legend()
# График заболеваемости в регионах (Логарифм от количества подтвержденных случаев - Дата)

fig, ax = plt.subplots(figsize=(15,10))
plt.plot(np.log(moscow_cases['Confirmed']+1), 'ro-', label = 'Moscow')
plt.plot(np.log(spb_cases['Confirmed']+1), 'go-', label = 'Saint-Petersburg')
plt.plot(np.log(nsk_cases['Confirmed']+1), 'bo-', label = 'Novosibirsk')
plt.grid()
plt.ylabel('Log(confirmed)')
plt.xlabel('Date')
plt.legend()
"""
Анализ графиков: исходя из данных графиков, из трех регионов Новосибирская область имеет наименьшие темпы роста числа подтвержденных случаев заболевания COVID-19 
"""
"""
# Часть 2. Прогноз развития COVID-19 в Новосибирской области на июнь.
"""
"""
Сравнительный анализ
"""
russia_regions = pd.read_csv('/kaggle/input/russia-regions-in-sber-covid-competition/russia_regions.csv')

import fetch
data = fetch.fetch_yandex(dump_folder='')
data, filepath = fetch.format_csse2(data, dump_folder='')
russia = pd.read_csv('https://raw.githubusercontent.com/grwlf/COVID-19_plus_Russia/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_confirmed_RU.csv')
russia_latest = pd.read_csv(filepath)
russia_latest
rus = russia.set_index('Province_State').join(russia_latest.set_index('Province_State')['Confirmed'])
rus
today = filepath[:10]
today2 = today[3:5]+'/'+today[:2]+'/'+today[-2:]
rus.drop(['UID','iso2','iso3','FIPS','Admin2','Country_Region','Lat','Long_','Combined_Key','code3'], axis=1, inplace=True)
rus[today2] = rus['Confirmed']
del rus['Confirmed']

del rus['06/09/20'] # Удаляем данные за июнь(позже добавим в нужном порядке)
df = rus.T.iloc[-30:,:]
df
df.plot(figsize=(15,10), legend=None)

plt.show()
"""
Из графика следует, что число заболевших COVID-19 в Москве гораздо выше, чем в остальных регионах => прологарифмируем
"""
(np.log(rus + 0.5).T).plot(figsize=(15,10), legend=None)

plt.show()

y = np.log(rus + 0.5).T
y_m = y[y>5]
y_m
y_m.count().max()
list_columns = []
for column in y_m.columns:
    list_columns.append(y_m[column].count())
    
filled = pd.Series(list_columns).max()
y_gt_148 = pd.DataFrame(data = [[0 for i in range(len(y_m.columns))] for j in range(filled)], index = range(filled), columns = y_m.columns)
y_gt_148
for i in range(len(y_m.columns)):
    temp = y_m.iloc[:,i].dropna().reset_index(drop=True)
    y_gt_148.iloc[:temp.shape[0],i] = temp
y_gt_148 = y_gt_148.replace(0,np.nan)
y_gt_148
y_gt_148.plot(figsize=(15,10), legend=None)

plt.show()
"""
Наполнили датафрейм с первого наблюдения, где 148+ кейсов в логарифмической шкале
"""
y_gt_148.iloc[0,:].max()
delta = y_gt_148.iloc[0,:].max() - y_gt_148.iloc[0,:]
all_in_one = y_gt_148 + delta
all_in_one.head()
all_in_one.plot(figsize=(15,10), legend=None)

plt.show()
# Автономные области не названы, поможем назвать

russia_regions.loc[russia_regions['iso_code'] == 'RU-NEN', 'csse_province_state'] = 'Nenetskiy autonomous oblast'
russia_regions.loc[russia_regions['iso_code'] == 'RU-CHU', 'csse_province_state'] = 'Chukotskiy autonomous oblast'
rus['ind'] = rus.index
# Altay republic > Republic of Altay
rus.loc[rus.index == 'Altay republic', 'ind'] = 'Republic of Altay'
rus.set_index('ind', inplace=True)
sorted_obl = russia_regions.sort_values(['population']).reset_index()

nsk_index = sorted_obl[sorted_obl['name']=='Новосибирская'].index[0]

sorted_obl[nsk_index-3:nsk_index+4]
selected_regions = list(sorted_obl[nsk_index-3:nsk_index+4]['csse_province_state'])
show_regions = selected_regions + ['Moscow']
all_in_one[show_regions]
all_in_one[show_regions].plot(figsize=(15,10))
plt.show()
(np.log(rus.loc[show_regions] + 0.5).T[-30:]).plot(figsize=(15,10))
plt.show()
"""
В двух представленных выше графиках показана динамика заболеваемости в Новосибирской области и 6 схожих по численности населения регионах
"""
last_30_days = np.log(rus.loc[show_regions] + 0.5).T[-30:]
last_30_days.head()
last_30_days = last_30_days - last_30_days.loc['05/02/20']
last_30_days.head()
last_30_days.plot(figsize=(15,10))

plt.show()
last_100_days = np.log(rus.loc[show_regions] + 0.5).T[-100:]
last_100_days.plot(figsize=(15,10))
plt.show()
d100 = last_100_days[last_100_days > 5]

filled2 = d100.count().max()
d100_eq = pd.DataFrame(data = [[0 for i in range(len(d100.columns))] for j in range(filled2)], \
                        index = range(filled2), columns = d100.columns)

# Наполним датафрейм с первого наблюдения, где 148+ кейсов в логарифмической шкале

for i in range(len(d100.columns)):
    temp = d100.iloc[:,i].dropna().reset_index(drop=True)
    d100_eq.iloc[:temp.shape[0],i] = temp
    
d100_eq = d100_eq.replace(0,np.nan)
print(d100_eq.iloc[0,:].max())
delta = d100_eq.iloc[0,:].max() - d100_eq.iloc[0,:]
d100_eq = d100_eq + delta

print(d100_eq.head())

d100_eq.plot()
plt.show()
d100.plot()
plt.show()
d100
"""
# Первый способ прогнозирования
"""
d100['Novosibirsk oblast'].dropna().plot(figsize=(15,10))
plt.show()
nsk = rus.loc['Novosibirsk oblast']
nsk
nsk['06/01/20'] = 2914
nsk['06/02/20'] = 3020
nsk['06/03/20'] = 3122
nsk['06/04/20'] = 3226
nsk['06/05/20'] = 3334
nsk['06/06/20'] = 3441
nsk['06/07/20'] = 3546
nsk['06/08/20'] = 3648
nsk['06/09/20'] = 3752
"""
Добавили недостающие значения на текущую дату
"""
nsk.tail()
nsk[nsk>150].plot(figsize=(15,10))
delta_nsk = nsk - nsk.shift() # предыдущие значения

delta_nsk = delta_nsk[delta_nsk>0]
delta_nsk.plot(figsize=(15,10))
plt.show()
log_nsk = np.log(nsk)
log_nsk = log_nsk[log_nsk>5]
log_nsk.plot(figsize=(15,10))
plt.show()
log_nsk.shape # размер
# Добавлены ячейки для прогнозирования (значение 1, т.к. логарифм от 0 не существует)
log_nsk['06/10/20'] = 1
log_nsk['06/11/20'] = 1
log_nsk['06/12/20'] = 1
log_nsk['06/13/20'] = 1
log_nsk['06/14/20'] = 1
log_nsk['06/15/20'] = 1
log_nsk['06/16/20'] = 1
log_nsk['06/17/20'] = 1
log_nsk['06/18/20'] = 1
log_nsk['06/19/20'] = 1
log_nsk['06/20/20'] = 1
log_nsk['06/21/20'] = 1
log_nsk['06/22/20'] = 1
log_nsk['06/23/20'] = 1
log_nsk['06/24/20'] = 1
log_nsk['06/25/20'] = 1
log_nsk['06/26/20'] = 1
log_nsk['06/27/20'] = 1
log_nsk['06/28/20'] = 1
log_nsk['06/29/20'] = 1
log_nsk['06/30/20'] = 1
log_nsk.shape
df_nsk = pd.DataFrame(data = {'date' : pd.to_datetime(log_nsk.index), 'Nsk' : log_nsk.values, 'X' : range(1,71)})
# Модель y = x^a или ln y = a * ln x, обучаем на 45 наблюдениях, делаем прогноз до конца июня (21 день)

X_train = np.log(df_nsk.loc[0:44,'X']).values.reshape(-1,1) 
y_train = np.log(df_nsk.loc[0:44,'Nsk']).values.reshape(-1,1)
X_test = np.log(df_nsk.loc[45:69,'X']).values.reshape(-1,1) 
X_train = np.log(df_nsk.loc[0 : 44,'X']).values.reshape(-1,1) 
y_train = np.log(df_nsk.loc[0 : 44,'Nsk']).values.reshape(-1,1)
X_test = np.log(df_nsk.loc[45 : 69, 'X']).values.reshape(-1,1) 

    # Скалируем признаки, для регрессии с регуляризацией хорошо
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
scaler.fit(X_train)

    # print(scaler.mean_, scaler.var_)
X_train_scaled = scaler.transform(X_train)
X_test_scaled = scaler.transform(X_test)

    # Строим регрессию
from sklearn.linear_model import LinearRegression
reg = LinearRegression().fit(X_train_scaled, y_train)

    # Функции для 2 метрик: первая - конкурсная, вторая - процент отклонения от истины
def MALE(pred, true):
    return np.mean(np.abs(np.log10((pred + 1) / (true + 1))))

def AvgProc(pred, true):
    return np.mean(np.abs((pred-true)/true))

    # Приводим у к кол-ву случаев
y_pred_test_exp = np.round(np.exp(np.exp(reg.predict(X_test_scaled))),0)
y_pred_train_exp = np.round(np.exp(np.exp(reg.predict(X_train_scaled))),0)
y_train_exp = np.round(np.exp(np.exp(y_train)),0)

plt.figure(figsize=(15,10))

plt.plot(df_nsk.loc[45 : 69,'date'], y_pred_test_exp) 
plt.plot(df_nsk.loc[0 : 44,'date'], y_pred_train_exp)
plt.plot(df_nsk.loc[0 : 44,'date'], y_train_exp)

plt.legend()
plt.legend()
plt.show()
plt.grid
"""
Прогноз показал, что на 1 июля в Новосибирской области численность подтвержденных случаев заражения COVID-19 составит порядка 5000 случаев. Но, как мы видим из графика, со временем различия между тестовой и обучаемой выборкой растут => фактические значения могут быть больше.
"""
"""
# Второй способ прогнозирования
"""
"""
Прогноз построен по авторегрессионной модели AR(10). Будем использовать готовые библиотеки. 
"""
"""
Тестовое предсказание на 10 дней
"""
from matplotlib import pyplot
from statsmodels.tsa.ar_model import AutoReg
from sklearn.metrics import mean_squared_error
from math import sqrt

X = log_nsk.values
train, test = X[1:len(X)-31], X[len(X)-31:len(X)-21] # Обучаем на 30 днях, прогнозируем - 10, для сравнения фактических значений с прогнозом

model = AutoReg(train, lags=10) # lag = 10, исходя из перебора значений, для наибольшей точности (RMSE при lag = 10 - наименьшая)
model_fit = model.fit()
print('Coefficients: %s' % model_fit.params)

predictions = model_fit.predict(start=len(train), end=len(train)+len(test)-1, dynamic=False)
for i in range(len(predictions)):
    print('predicted=%f, expected=%f' % (predictions[i], test[i]))
rmse = sqrt(mean_squared_error(test, predictions))
print('Test RMSE: %.3f' % rmse) # RMSE - среднеквадратическая ошибка прогноза

pyplot.plot(test)
pyplot.plot(predictions, color='red')
pyplot.show()
"""
Итоговое прогнозирование с 10 по 30 июня (включительно)
"""
X = log_nsk.values
train, test = X[1:len(X)-21], X[len(X)-21:] # Обучаем на 39 днях, прогнозируем - 21

model = AutoReg(train, lags=10)
model_fit = model.fit()
print('Coefficients: %s' % model_fit.params)

predictions = model_fit.predict(start=len(train), end=len(train)+len(test)-1, dynamic=False)
for i in range(len(predictions)):
    print('predicted=%f' % (predictions[i]))

pyplot.plot(predictions, color='red')
pyplot.show()
"""
*По данным прогноза, построенного по авторегрессионной модели AR(10) численность подтвержденных случаев COVID-19 в Новосибирской области на 1 июля 2020г составит порядка 6000, (ось y - логарифм от количества случаев, x - номер прогнозируемого дня (10 - 30 июня)). При обучении выборки, RMSE оказалась достаточно маленькой, причем прогнозируемые значения оказались выше фактических => из двух прогнозов данный отличается большей точностью. С точки зрения подхода данный прогноз более консервативный.  *
"""
"""
# Часть 3. Построение графиков. Динамика развития (заболеваемость, смертность) COVID-19 в нескольких странах мира.
"""
# Загружаем и редактируем данные о заболеваемости в мире

world_cases = pd.read_csv('/kaggle/input/updatedjohn/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_confirmed_global.csv')
world_cases = world_cases.groupby('Country/Region').sum()
world_cases.drop(['Lat', 'Long'], axis=1, inplace=True)
world_cases = world_cases.T
world_cases
# График заболеваемости в России, Германии, США, Италии, Китае (Количество подтвержденных случаев - Дата)

fig, ax = plt.subplots(figsize=(15,10))
plt.plot(world_cases['Russia'], 'r.-', label = 'Russia')
plt.plot(world_cases['Germany'], 'g.-', label = 'Germany')
plt.plot(world_cases['US'], 'b.-', label = 'US')
plt.plot(world_cases['Italy'], 'y.-', label = 'Italy')
plt.plot(world_cases['China'], 'c.-', label = 'China')
plt.ylabel('Confirmed')
plt.xlabel('Date')
plt.grid()
plt.legend()
# График заболеваемости в России, Германии, США, Италии, Китае (Логарифм от количества подтвержденных случаев - Дата)

fig, ax = plt.subplots(figsize=(15,10))
plt.plot(np.log(world_cases['Russia']+1), 'r.-', label = 'Russia')
plt.plot(np.log(world_cases['Germany']+1), 'g.-', label = 'Germany')
plt.plot(np.log(world_cases['US']+1), 'b.-', label = 'US')
plt.plot(np.log(world_cases['Italy']+1), 'y.-', label = 'Italy')
plt.plot(np.log(world_cases['China']+1), 'c.-', label = 'China')
plt.ylabel('Log(confirmed)')
plt.xlabel('Date')
plt.grid()
plt.legend()
# Загружаем и редактируем данные о смертности в мире

world_deaths = pd.read_csv('/kaggle/input/updatedjohn/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_deaths_global.csv')
world_deaths = world_deaths.groupby('Country/Region').sum()
world_deaths.drop(['Lat', 'Long'], axis=1, inplace=True)
world_deaths = world_deaths.T
# График смертности в России, Германии, США, Италии, Китае (Количество смертей от COVID-19 - Дата)

fig, ax = plt.subplots(figsize=(15,10))
plt.plot(world_deaths['Russia'], 'r.-', label = 'Russia')
plt.plot(world_deaths['Germany'], 'g.-', label = 'Germany')
plt.plot(world_deaths['US'], 'b.-', label = 'US')
plt.plot(world_deaths['Italy'], 'y.-', label = 'Italy')
plt.plot(world_deaths['China'], 'c.-', label = 'China')
plt.ylabel('Died')
plt.xlabel('Date')
plt.grid()
plt.legend()
# График смертности в России, Германии, США, Италии, Китае (Логарифм от количества смертей - Дата)

fig, ax = plt.subplots(figsize=(15,10))
plt.plot(np.log(world_deaths['Russia']+1), 'r.-', label = 'Russia')
plt.plot(np.log(world_deaths['Germany']+1), 'g.-', label = 'Germany')
plt.plot(np.log(world_deaths['US']+1), 'b.-', label = 'US')
plt.plot(np.log(world_deaths['Italy']+1), 'y.-', label = 'Italy')
plt.plot(np.log(world_deaths['China']+1), 'c.-', label = 'China')
plt.ylabel('Log(died)')
plt.xlabel('Date')
plt.grid()
plt.legend()
"""
# Here is the end of the presentation
"""