Corporación Favorita — эквадорский конгломерат магазинов самообслуживания, инвестиций в недвижимость, производства электроэнергии, продуктов питания и предметов первой необходимости, торговли и оборудования. Компания присутствует в Эквадоре, Перу, Парагвае и Панаме. Супермаркеты La Favorita CA были основаны 26 ноября 1957 года. Это был первый супермаркет самообслуживания в Эквадоре.

В этом проекте мы будем использовать прогнозирование временных рядов для прогнозирования продаж магазинов на основе данных от Corporación Favorita для тысяч семейств продуктов, продаваемых в магазинах Favorita. Данные обучения включают даты, информацию о магазине и продукте, информацию о том, рекламировался ли этот товар, а также количество продаж.

Для продуктовых магазинов более точное прогнозирование может уменьшить количество пищевых отходов, связанных с затовариванием, и повысить удовлетворенность покупателей.

Мы используем этот набор данных от Kaggle.

Источник набора данных: https://www.kaggle.com/competitions/store-sales-time-series-forecasting

Как запустить код

Это руководство представляет собой исполняемый блокнот Jupyter, размещенный на Jovian. Вы можете запустить это руководство и поэкспериментировать с примерами кода двумя способами: используя бесплатные онлайн-ресурсы (рекомендуется) или на своем компьютере.

Вариант 1. Использование бесплатных онлайн-ресурсов (рекомендуется в один клик)

Самый простой способ начать выполнение кода — нажать кнопку «Выполнить» в верхней части этой страницы и выбрать «Выполнить на Binder». Вы также можете выбрать «Запустить на Colab» или «Запустить на Kaggle», но для использования этих платформ вам потребуется создать учетную запись в Google Colab или Kaggle.

Вариант 2. Запуск на локальном компьютере

Чтобы запустить код на вашем компьютере локально, вам нужно настроить Python, загрузить блокнот и установить необходимые библиотеки. Мы рекомендуем использовать дистрибутив Python Conda. Нажмите кнопку «Выполнить» в верхней части этой страницы, выберите параметр «Выполнить локально» и следуйте инструкциям.

Описание набора данных

Описания файлов и информация о полях данных

  • train.csv
  • store_nbr: определяет магазин, в котором продаются товары.
  • семейство: определяет тип продаваемого продукта.
  • продажи: дает общий объем продаж для семейства продуктов в конкретном магазине на заданную дату. Дробные значения возможны, так как продукты могут продаваться в дробных единицах (например, 1,5 кг сыра вместо 1 пакета чипсов).
  • onpromotion: показывает общее количество товаров в семействе продуктов, которые рекламировались в магазине на указанную дату.
  • test.csv
  • Тестовые данные, имеющие те же характеристики, что и обучающие данные. Мы будем прогнозировать целевые продажи для дат в этом файле.
  • Даты в тестовых данных относятся к 15 дням после последней даты в обучающих данных.
  • sample_submission.csv
  • Образец файла отправки в правильном формате.
  • stores.csv
  • Храните метаданные, включая город, штат, тип и кластер.
  • кластер — это группа похожих магазинов.
  • oil.csv
  • Ежедневная цена на нефть. Включает значения как во время обучения, так и во время тестовых данных. (Эквадор — страна, зависящая от нефти, и ее экономическое здоровье очень уязвимо к скачкам цен на нефть.)
  • holidays_events.csv
  • Праздники и события с метаданными
  • ПРИМЕЧАНИЕ. Обратите особое внимание на переданную колонку. Перенесенный праздник официально приходится на этот календарный день, но правительство перенесло его на другую дату. Перенесенный день больше похож на обычный день, чем на праздник. Чтобы найти день его празднования, найдите соответствующую строку, где тип — «Перенос». Например, праздник Independencia de Guayaquil был перенесен с 2012–10–09 на 2012–10–12, что означает, что он отмечался 2012–10–12. Дни типа «Мост» — это дополнительные дни, которые добавляются к празднику (например, чтобы продлить перерыв на длинные выходные). Они часто состоят из типа «Рабочий день», который обычно не запланирован для работы (например, суббота), который предназначен для окупаемости Моста.
  • Дополнительные праздники — это дни, добавленные к обычному календарному празднику, например, как это обычно бывает на Рождество (что делает Сочельник выходным днем).
  • Дополнительные примечания Заработная плата в бюджетной сфере выплачивается каждые две недели 15 числа и в последний день месяца. Это может повлиять на продажи в супермаркетах. Землетрясение магнитудой 7,8 произошло в Эквадоре 16 апреля 2016 года. Люди объединились для оказания помощи, пожертвовав воду и другие предметы первой необходимости, что сильно повлияло на продажи в супермаркетах в течение нескольких недель после землетрясения.

Выявление проблемы

Продажи — это помеченная непрерывная числовая характеристика. Следовательно, это приложение Supervised ML, в частности, это проблема регрессии.

Метрика оценки

Показателем оценки для этого соревнования является среднеквадратическая логарифмическая ошибка.

RMSLE рассчитывается как:

$$RMSLE = \sqrt{ \frac{1}{n} \sum_{i=1}^n \left(\log (1 + \hat{y}_i) — \log (1 + y_i)\right)²}$$

где:

$n$ — общее количество экземпляров,

$\hat{y}_i$ — прогнозируемое значение цели для экземпляра (i),

${y}_i$ — фактическое значение цели, например (i)

$log$ — натуральный логарифм.

Скачать набор данных

Установите и импортируйте необходимые библиотеки

!pip install --upgrade pandas "dask[complete]" --quiet
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 12.3/12.3 MB 75.2 MB/s eta 0:00:00
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.2/1.2 MB 61.5 MB/s eta 0:00:00
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 341.8/341.8 kB 31.7 MB/s eta 0:00:00
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.3/1.3 MB 73.7 MB/s eta 0:00:00
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 980.4/980.4 kB 42.7 MB/s eta 0:00:00
[?25hERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.
google-colab 1.0.0 requires pandas==1.5.3, but you have pandas 2.0.3 which is incompatible.

!pip install opendatasets seaborn matplotlib plotly scikit-learn xgboost lightgbm --upgrade --quiet
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 11.6/11.6 MB 33.9 MB/s eta 0:00:00
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 15.5/15.5 MB 23.3 MB/s eta 0:00:00
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 10.8/10.8 MB 30.5 MB/s eta 0:00:00
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 98.3/98.3 kB 11.1 MB/s eta 0:00:00
[?25h
# Import library to download data from Kaggle
import opendatasets as od

import os
import random

import pandas as pd  # data processing, CSV file I/O (e.g. pd.read_csv)
import numpy as np  # linear algebra

import warnings
warnings.filterwarnings('ignore')
# Visualisation libraries
import matplotlib
import matplotlib.pyplot as plt
import seaborn as sns
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import plotly.express as px
%matplotlib inline

# Configuring styles
sns.set_style("darkgrid")
plt.rcParams['font.size'] = 14
plt.rcParams['figure.figsize'] = (15, 6)
plt.rcParams['figure.facecolor'] = '#00000000'
#Models Packages
from sklearn import metrics
from sklearn.metrics import mean_squared_log_error
from sklearn import feature_selection
from sklearn.model_selection import train_test_split
from sklearn import preprocessing
from sklearn.preprocessing import MinMaxScaler
from sklearn.preprocessing import OneHotEncoder
import random
pd.options.display.float_format = '{:,.2f}'.format

from sklearn.linear_model import LinearRegression, Ridge, SGDRegressor
from sklearn.tree import DecisionTreeRegressor
from sklearn.ensemble import RandomForestRegressor
import xgboost as xgb
from xgboost import XGBRegressor
import lightgbm as lgb
from lightgbm import LGBMRegressor

Загрузка данных

dataset_url = 'https://www.kaggle.com/competitions/store-sales-time-series-forecasting'
od.download(dataset_url)
Downloading store-sales-time-series-forecasting.zip to ./store-sales-time-series-forecasting


100%|██████████| 21.4M/21.4M [00:00<00:00, 34.8MB/s]



Extracting archive ./store-sales-time-series-forecasting/store-sales-time-series-forecasting.zip to ./store-sales-time-series-forecasting
data_dir = "store-sales-time-series-forecasting"

Просмотр файлов набора данных

os.listdir(data_dir)
['train.csv',
 'test.csv',
 'oil.csv',
 'transactions.csv',
 'stores.csv',
 'sample_submission.csv',
 'holidays_events.csv']
train_df = pd.read_csv(data_dir+'/train.csv')
test_df = pd.read_csv(data_dir+'/test.csv')
transactions_df = pd.read_csv(data_dir+'/transactions.csv')
stores_df = pd.read_csv(data_dir+'/stores.csv')
oil_df = pd.read_csv(data_dir+'/oil.csv')
holidays_df = pd.read_csv(data_dir+'/holidays_events.csv')
print('Training dataset length:', len(train_df))
print('Test dataset length:', len(test_df))
print('Transactions dataset length:', len(transactions_df))
print('Stores dataset length:', len(stores_df))
print('Oil dataset length:', len(oil_df))
print('Holidays events dataset length:', len(holidays_df))
Training dataset length: 3000888
Test dataset length: 28512
Transactions dataset length: 83488
Stores dataset length: 54
Oil dataset length: 1218
Holidays events dataset length: 350
print('Training dataset Shape:', (train_df.shape))
print('Test dataset Shape:', (test_df.shape))
print('Transactions dataset Shape:', (transactions_df.shape))
print('Stores dataset Shape:', (stores_df.shape))
print('Oil dataset Shape:', (oil_df.shape))
print('Holidays events dataset Shape:', (holidays_df.shape))
Training dataset Shape: (3000888, 6)
Test dataset Shape: (28512, 5)
Transactions dataset Shape: (83488, 3)
Stores dataset Shape: (54, 5)
Oil dataset Shape: (1218, 2)
Holidays events dataset Shape: (350, 6)
train_df.head()

test_df.head()

Набор данных содержит более 3 миллионов строк и 6 столбцов в обучающих данных и более 28 тысяч строк и 5 столбцов в тестовых данных.

Мы будем использовать только 1% обучающих данных для обучения модели.

sample_fraction = 0.1

def skip_row(row_idx):
  if row_idx == 0:
    return False
  return random.random() > sample_fraction

# Loading the data with skip rows
random.seed(42)
train_df = pd.read_csv(data_dir+'/train.csv',
                 skiprows=skip_row)

Исследуйте набор данных

train_df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 300730 entries, 0 to 300729
Data columns (total 6 columns):
 #   Column       Non-Null Count   Dtype  
---  ------       --------------   -----  
 0   id           300730 non-null  int64  
 1   date         300730 non-null  object 
 2   store_nbr    300730 non-null  int64  
 3   family       300730 non-null  object 
 4   sales        300730 non-null  float64
 5   onpromotion  300730 non-null  int64  
dtypes: float64(1), int64(3), object(2)
memory usage: 13.8+ MB
train_df.describe()

test_df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 28512 entries, 0 to 28511
Data columns (total 5 columns):
 #   Column       Non-Null Count  Dtype 
---  ------       --------------  ----- 
 0   id           28512 non-null  int64 
 1   date         28512 non-null  object
 2   store_nbr    28512 non-null  int64 
 3   family       28512 non-null  object
 4   onpromotion  28512 non-null  int64 
dtypes: int64(3), object(2)
memory usage: 1.1+ MB
stores_df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 54 entries, 0 to 53
Data columns (total 5 columns):
 #   Column     Non-Null Count  Dtype 
---  ------     --------------  ----- 
 0   store_nbr  54 non-null     int64 
 1   city       54 non-null     object
 2   state      54 non-null     object
 3   type       54 non-null     object
 4   cluster    54 non-null     int64 
dtypes: int64(2), object(3)
memory usage: 2.2+ KB
transactions_df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 83488 entries, 0 to 83487
Data columns (total 3 columns):
 #   Column        Non-Null Count  Dtype 
---  ------        --------------  ----- 
 0   date          83488 non-null  object
 1   store_nbr     83488 non-null  int64 
 2   transactions  83488 non-null  int64 
dtypes: int64(2), object(1)
memory usage: 1.9+ MB
transactions_df.describe()

oil_df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1218 entries, 0 to 1217
Data columns (total 2 columns):
 #   Column      Non-Null Count  Dtype  
---  ------      --------------  -----  
 0   date        1218 non-null   object 
 1   dcoilwtico  1175 non-null   float64
dtypes: float64(1), object(1)
memory usage: 19.2+ KB
oil_df.describe()

holidays_df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 350 entries, 0 to 349
Data columns (total 6 columns):
 #   Column       Non-Null Count  Dtype 
---  ------       --------------  ----- 
 0   date         350 non-null    object
 1   type         350 non-null    object
 2   locale       350 non-null    object
 3   locale_name  350 non-null    object
 4   description  350 non-null    object
 5   transferred  350 non-null    bool  
dtypes: bool(1), object(5)
memory usage: 14.1+ KB
train_df.family.nunique(), train_df.family.unique()
(33,
 array(['BABY CARE', 'CLEANING', 'DELI', 'GROCERY I', 'LADIESWEAR',
        'PET SUPPLIES', 'PLAYERS AND ELECTRONICS', 'DAIRY', 'FROZEN FOODS',
        'LIQUOR,WINE,BEER', 'MAGAZINES', 'POULTRY', 'PERSONAL CARE',
        'SEAFOOD', 'BEAUTY', 'BOOKS', 'AUTOMOTIVE', 'HOME CARE',
        'LINGERIE', 'BREAD/BAKERY', 'SCHOOL AND OFFICE SUPPLIES', 'EGGS',
        'CELEBRATION', 'GROCERY II', 'HOME AND KITCHEN I', 'HARDWARE',
        'MEATS', 'PREPARED FOODS', 'HOME AND KITCHEN II',
        'HOME APPLIANCES', 'BEVERAGES', 'PRODUCE', 'LAWN AND GARDEN'],
       dtype=object))
train_df.store_nbr.nunique()
54
stores_df[['city','state','type','cluster']].nunique(), stores_df.type.unique()
(city       22
 state      16
 type        5
 cluster    17
 dtype: int64,
 array(['D', 'B', 'C', 'E', 'A'], dtype=object))

Мы выяснили, что в 54 магазинах в 22 городах, расположенных в 16 штатах, продается 33 товарных семейства. Магазины делятся на 5 типов: «А», «В», «С», «D» и «Е». Также есть 17 кластеров, т.е. группировка похожих магазинов.

Заполнение отсутствующих значений в oil_df

def fill_nan_with_mean(df, column_name):
    values = df[column_name].values
    is_nan = np.isnan(values)
    filled_values = values.copy()

    for i in range(1, len(filled_values)-1):
        if np.isnan(filled_values[i]):
            prev_val = filled_values[i-1]
            next_val = filled_values[i+1]
            if not np.isnan(prev_val) and not np.isnan(next_val):
                filled_values[i] = (prev_val + next_val) / 2

    df[column_name] = filled_values
    return df
fill_nan_with_mean(oil_df, 'dcoilwtico')

oil_df[oil_df.dcoilwtico.isna()]

Тем не менее у нас есть 3 nan(s), заполняя их вручную

oil_df.dcoilwtico[0] = 93.14  # filling the first value similar to second value
print(oil_df.loc[1173])
date          2017-06-30
dcoilwtico         46.02
Name: 1173, dtype: object
# filling these two similar to the previous value
oil_df.dcoilwtico[1174]=46.02
oil_df.dcoilwtico[1175]=46.02
oil_df.isna().sum()
date          0
dcoilwtico    0
dtype: int64

Манипуляции с данными и очистка

Преобразуем даты в datetime

train_df["date"] = pd.to_datetime(train_df["date"])
test_df['date'] = pd.to_datetime(test_df['date'])
transactions_df['date'] = pd.to_datetime(transactions_df['date'])
oil_df['date'] = pd.to_datetime(oil_df['date'])
holidays_df['date'] = pd.to_datetime(holidays_df['date'])

Мы объединим train_df и test_df с store_df, oil_df и holiday_df. В holiday_df «locale_name» — это город, поэтому мы должны переименовать столбец как город. В магазинах и праздниках столбец «тип» одинаков, поэтому мы должны переименовать их как store_type и day_type. В oil_df «dcoilwtico» — это цена на нефть, поэтому мы также переименуем этот столбец. Нам не нужно описание праздников, поэтому мы опустим этот столбец.

stores_df.rename(columns = {'type':'store_type'}, inplace=True)
oil_df.rename(columns = {'dcoilwtico':'oil_price'}, inplace=True)
holidays_df.rename(columns = {'locale_name':'city', 'type': 'day_type'}, inplace=True)
holidays_df.drop('description', axis=1, inplace=True)

Теперь объединяем разные наборы данных

merged_train_df = train_df.merge(stores_df, how='left', on='store_nbr')
merged_test_df = test_df.merge(stores_df, how='left', on='store_nbr')

merged_train_df = pd.merge(merged_train_df, oil_df, how='left', on='date')
merged_test_df = pd.merge(merged_test_df, oil_df, how='left', on='date')

merged_train_df = pd.merge(merged_train_df, holidays_df, how='left', on=['date', 'city'])
merged_test_df = pd.merge(merged_test_df, holidays_df, how='left', on=['date', 'city'])
merged_train_df

merged_test_df

Заполнение значений nan в объединенном наборе данных

# Filling the nan(s) with the value before nan because oil prices don't change very much every other day
merged_train_df['oil_price'].fillna(method = 'ffill', inplace=True)
merged_test_df['oil_price'].fillna(method = 'ffill', inplace=True)

# 'day_type' is filled with holidays, so all nan(s) are working days
merged_train_df['day_type'].fillna('working_day',inplace=True)
merged_test_df['day_type'].fillna('working_day',inplace=True)

# All the NaN value in 'locale' column are working days hence it is National
merged_train_df['locale'].fillna('National', inplace=True)
merged_test_df['locale'].fillna('National', inplace=True)

# All the NaN values are working days hence not tranferred
merged_train_df['transferred'].fillna(False, inplace=True)
merged_test_df['transferred'].fillna(False, inplace=True)

изменение типов данных столбцов

merged_train_df['store_nbr']= merged_train_df['store_nbr'].astype('uint8')
merged_train_df['sales']= merged_train_df['sales'].astype('float64')
merged_train_df['onpromotion']=merged_train_df['onpromotion'].astype('uint16')
merged_train_df['cluster']= merged_train_df['cluster'].astype('uint8')
merged_train_df['oil_price']= merged_train_df['oil_price'].astype('float64')
merged_train_df['transferred'] = merged_train_df['transferred'].astype('uint8')

merged_test_df['store_nbr']= merged_test_df['store_nbr'].astype('uint8')
merged_test_df['onpromotion']= merged_test_df['onpromotion'].astype('uint16')
merged_test_df['cluster']= merged_test_df['cluster'].astype('uint8')
merged_test_df['oil_price']= merged_test_df['oil_price'].astype('float64')
merged_test_df['transferred'] = merged_test_df['transferred'].astype('uint8')

Замена значений «семейства» добавлением «подчеркивания» в «пробел», потому что это приводит к ошибке во время обучения легкой модели GBM.

def replace_fam_vals(df):
  df.replace('HOME APPLIANCES','HOME_APPLIANCES',inplace=True)
  df.replace('BABY CARE','BABY_CARE',inplace=True)
  df.replace('BREAD/BAKERY','BREAD_BAKERY',inplace=True)
  df.replace('FROZEN FOODS','FROZEN_FOODS',inplace=True)
  df.replace('GROCERY I','GROCERY_I',inplace=True)
  df.replace('GROCERY II','GROCERY_II',inplace=True)
  df.replace('HOME AND KITCHEN I','HOME_AND_KITCHEN_I',inplace=True)
  df.replace('HOME AND KITCHEN II','HOME_AND_KITCHEN_II',inplace=True)
  df.replace('HOME CARE','HOME_CARE',inplace=True)
  df.replace('LAWN AND GARDEN','LAWN_AND_GARDEN',inplace=True)
  df.replace('LIQUOR,WINE,BEER','LIQUOR_WINE_BEER',inplace=True)
  df.replace('PERSONAL CARE','PERSONAL_CARE',inplace=True)
  df.replace('PET SUPPLIES','PET_SUPPLIES',inplace=True)
  df.replace('PLAYERS AND ELECTRONICS','PLAYERS_AND_ELECTRONICS',inplace=True)
  df.replace('PREPARED FOODS','PREPARED_FOODS',inplace=True)
  df.replace('SCHOOL AND OFFICE SUPPLIES','SCHOOL_AND_OFFICE_SUPPLIES',inplace=True)
  return df
replace_fam_vals(merged_train_df.family)
replace_fam_vals(merged_test_df.family)
0                        AUTOMOTIVE
1                         BABY_CARE
2                            BEAUTY
3                         BEVERAGES
4                             BOOKS
                    ...            
28507                       POULTRY
28508                PREPARED_FOODS
28509                       PRODUCE
28510    SCHOOL_AND_OFFICE_SUPPLIES
28511                       SEAFOOD
Name: family, Length: 28512, dtype: object
merged_train_df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 300754 entries, 0 to 300753
Data columns (total 14 columns):
 #   Column       Non-Null Count   Dtype         
---  ------       --------------   -----         
 0   id           300754 non-null  int64         
 1   date         300754 non-null  datetime64[ns]
 2   store_nbr    300754 non-null  uint8         
 3   family       300754 non-null  object        
 4   sales        300754 non-null  float64       
 5   onpromotion  300754 non-null  uint16        
 6   city         300754 non-null  object        
 7   state        300754 non-null  object        
 8   store_type   300754 non-null  object        
 9   cluster      300754 non-null  uint8         
 10  oil_price    300754 non-null  float64       
 11  day_type     300754 non-null  object        
 12  locale       300754 non-null  object        
 13  transferred  300754 non-null  uint8         
dtypes: datetime64[ns](1), float64(2), int64(1), object(6), uint16(1), uint8(3)
memory usage: 24.4+ MB
merged_train_df.describe()

Проверка дубликатов

merged_train_df.duplicated().sum()
0

Проверка даты начала и окончания данных

merged_train_df.date.min(), merged_train_df.date.max()
(Timestamp('2013-01-01 00:00:00'), Timestamp('2017-08-15 00:00:00'))
merged_test_df.date.min(), merged_test_df.date.max()
(Timestamp('2017-08-16 00:00:00'), Timestamp('2017-08-31 00:00:00'))

Данные обучения с 1 января 2013 г. по 15 августа 2017 г.

Данные испытаний с 16 августа 2017 г. по 31 августа 2017 г.

Разработка функций

Создание новых столбцов с использованием столбца даты

merged_train_df['year'] = merged_train_df['date'].dt.year
merged_train_df['month'] = merged_train_df['date'].dt.month
merged_train_df['week'] = merged_train_df['date'].dt.isocalendar().week
merged_train_df['quarter'] = merged_train_df['date'].dt.quarter
merged_train_df['day_of_week'] = merged_train_df['date'].dt.dayofweek

merged_test_df['year'] = merged_test_df['date'].dt.year
merged_test_df['month'] = merged_test_df['date'].dt.month
merged_test_df['week'] = merged_test_df['date'].dt.isocalendar().week
merged_test_df['quarter'] = merged_test_df['date'].dt.quarter
merged_test_df['day_of_week'] = merged_test_df['date'].dt.dayofweek

Изменение типов данных столбцов

merged_train_df['month'] = merged_train_df['month'].astype('uint8')
merged_train_df['year'] = merged_train_df['year'].astype('uint16')
merged_train_df['week'] = merged_train_df['week'].astype('uint8')
merged_train_df['quarter'] = merged_train_df['quarter'].astype('uint8')
merged_train_df['day_of_week'] = merged_train_df['day_of_week'].astype('uint16')

merged_test_df['month'] = merged_test_df['month'].astype('uint8')
merged_test_df['year'] = merged_test_df['year'].astype('uint16')
merged_test_df['week'] = merged_test_df['week'].astype('uint8')
merged_test_df['quarter'] = merged_test_df['quarter'].astype('uint8')
merged_test_df['day_of_week'] = merged_test_df['day_of_week'].astype('uint16')

Исследовательский анализ данных

1. Цена на нефть

date_oil_price = merged_train_df.groupby('date')[['oil_price']].mean()
year_oil_price = merged_train_df.groupby('year')[['oil_price']].mean()
# plotting daily and yearly oil price
fig, axes = plt.subplots(1,2, figsize=(12,5))
date_oil_price.plot(ax=axes[0])
year_oil_price.plot(ax=axes[1])
axes[0].set_title("Daily oil price")
axes[1].set_title("Yearly oil price");

Информация

  • Цены на нефть были максимальными в 2013 году, но в 2015 году наблюдается резкое снижение цен, а в 2016 году цены были минимальными.

2. Продажи в день

date_sales = merged_train_df.groupby('date')[['sales']].sum().reset_index()
# plotting The date vs sales  line plot w.r.t to year
px.line(date_sales, x ='date',y ='sales', title='line plot of date vs. sales')