Анализ временных рядов в Tableau и R

Автор статьи — Мария Мазюк

Анализ временных рядов

Анализ временных рядов помогает выявить сезонные колебания метрик (например, объемов продаж) и тренд во времени, а также построить прогноз для заданного периода в будущем. Данный анализ может дать бизнесу 2 главных преимущества:

1.Выявление сезонных колебаний помогает спланировать логистику в компании и занятость работников: если вы знаете в какие месяцы / недели / дни вам потребуется больше материалов / курьеров / машин для удовлетворения повышенного спроса, вам будет проще спланировать аренду складов и машин заранее, а также закупить сырье на более выгодных условиях. Также выявление сезонных трендов поможет в планировании привлечения дополнительных временных работников и расписания отпусков, распределении рекламного бюджета.

2.Построение прогноза на основании общего и сезонных трендов помогает задать плановые показатели продаж / выручки / прибыли / расходов на сырье в будущем при прочих равных условиях. В случае невыполнения плана это поможет выявить недоработки. В случае нововведений для оптимизации процессов отличие реальных цифр от плана поможет установить эффект от внедрения нововведений.

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

Важно отметить, что если в качестве прогнозируемой переменной планируется использовать показатель в денежном выражении (например, объем продаж в рублях), и если инфляция имела место в рассматриваемом периоде, то перед началом работы с временными рядами следует перевести денежный показатель в эквивалент настоящего периода. Этот дополнительный шаг особенно важен при рассмотрении длительного периода в несколько лет, где имели место значительные колебания курса валюты и цен. Например, для валюты USD я использовала данный калькулятор инфляции. Если на момент создания прогноза уже известен прогнозируемый показатель инфляции на ближайшие месяцы или год, их также лучше учесть при задании плановых показателей, а также корректировать плановые показатели с учетом новых условий.

В написании данной статьи мне помогло видео о построении прогноза временных рядов в RStudio Адама Чек и курс Forecasting in R в DataCamp.

Выявление тренда и сезонности с помощью визуализации в Tableau

Если данные с временными рядами уже скорректированы с учетов инфляции в прошлом, можно приступать в предварительному анализу в Tableau. В качестве примера я использую датасет Superstore.

Начинать работу с временными рядами следует с предварительного анализа, который призван ответить на следующие вопросы:

1. Имеет ли место общий тренд? Для этого можно использовать встроенный инструмент Trend Line в Tableau на вкладке Analytics.

2. Присутствуют ли сезонные колебания во временных рядах, привязанные к календарному году? Для этого используются графики разницы между периодами временных рядов.

3. Присутствуют ли цикличность во временных рядах, привязанная к экономическим циклам и циклам в отрасли? Для этого понадобятся данные за более длительный период, чем для выявления сезонных колебаний. Анализ цикличности находится за рамками данной статьи.

4. Если сезонные колебания и цикличность не выявлены, имеет ли место “белый шум” (white noise), т.е. изменения показателей абсолютно случайны и не имеют закономерностей? Случайность временных рядов можно измерить с помощью автокорреляции, а проверить временные ряды на наличие белого шума можно с помощью теста Ljung-Box. Подробнее об автокорреляции и тесте Ljung-Box можно узнать в курсе Forecasting in R в DataCamp. Автокорреляция и тест Ljung-Box находятся за рамками данной статьи.

Начнем с базового линейного графика продаж Time Plot с детализацией по месяцам. Из графика мы можем сделать вывод, что объемы продаж сильно колеблются по месяцам, и общий линейный тренд растущий. Линейные временные графики для длительного периода помогают увидеть колебания показателя во времена экономических спадов (цикличность).

Для облегчения выявления сезонных колебаний мы исключим тренд и визуализируем лишь разницу в объемах продаж между периодами (в нашем случае — между месяцами). В Tableau это можно легко сделать с помощью быстрых табличных вычислений: Quick Table Calculation >> Difference. По умолчанию разница рассчитывается как Table (across), и нам это подходит.

Таким образом, у нас получился плоский стационарный (относительно общего тренда) график разницы объемов продаж по месяцам. Здесь мы можем наблюдать сильные колебания показателя по месяцам. Из данного графика можно сделать следующие предварительные выводы: 1) в марте, сентябре и ноябре положительная разница по сравнению с предыдущими месяцами кажется наибольшей; 2) в январе и октябре наблюдаются сильнейшие падения показателя по сравнению с предыдущими месяцами.

Далее нам следует выяснить, действительно ли данные колебания зависят от месяца (являются сезонными), т.е. являются ежегодной закономерностью или неупорядоченными? Для ответа на вопрос я построила два графика разницы объемов продаж по дискретным месяцам. Обратите внимание, что для построения графика использована именно разница показателя по периодам (месяцам конкретных годов), а не исходные значения показателя, чтобы исключить влияние общего тренда. На первом графике я разделила года цветом. На графике видно, что в январе и октябре объем продаж падает каждый год по сравнению с предыдущими месяцами, декабрем и сентябрем соответственно (разница является отрицательной). Наибольший сравнительный рост наблюдается в марте, сентябре и ноябре каждый год.

На втором графике я построила тренд по годам для каждого месяца по отдельности. На график также добавлена линия среднего значения (Average Line из панели Analytics) для каждого дискретного месяца (Pane). Здесь можно сделать аналогичные выводы: сильнейшее падение наблюдается в январе и октябре, а рост — в марте, сентябре и ноябре.

В результате анализа выявлены сезонные тренды объемов продаж по месяцам. Причин сезонности может быть много в зависимости от бизнеса. Результаты такого анализа уже можно применять для планирования бизнес-процессов на год вперед. Будет также полезным провести данный анализ на разных уровнях детализации для поиска точек роста: например, по категориям товаров или услуг, на уровне регионов, на уровне менеджеров по продажам и т.д.

Итак, во временных рядах объемов продаж по месяцам Superstore наблюдаются общий тренд и сезонные колебания. Время перейти к прогнозированию объемов продаж в следующем году.

Построение прогноза в R

Для построения прогноза временных рядов мы будем использовать пакет fpp2 в R. Пакет fpp2 — это объединение пакетов forecast и ggplot2. Мы используем три метода прогнозирования из пакета fpp2. Мы выберем модель, а затем построим график с прогнозными значениями объемов продаж на основании выбранной модели.

Перед началом работы с временными рядами с помощью пакета fpp2 необходимо перевести датасет с временными рядами в класс time series с помощью функции ts(). При этом в качестве временных рядов указывается только поле со значениями показателя (без дат), указывается частота в год (аргумент frequency) и начало отсчета времени (аргумент start).

library(fpp2)
# Load Superstore data with 2 fields: Date and Sales
Sales <- read.csv('superstore-sales.csv')
# Convert Superstore dataset into time series
Sales <- ts(Sales[,2], start = c(2016, 1), frequency = 12)

При оценке модели мы будем учитывать следующее:

1) корреляцию остатков (разниц прогнозируемых значений от реальных значений показателя — residuals). В модели, хорошо описывающей наблюдения, не должно быть корреляции между остатками: график автокорреляции (ACF) должен выглядеть, как белый шум. Значение p-value теста Ljung-Box должно быть меньше порогового (0.05), и распределение остатков должно быть нормальным.

2) стандартное отклонение остатков (Residual SD): лучше та модель, у которой стандартное отклонение остатков является минимальным.

Первый метод, который мы рассмотрим — это Naive method. Это самый простой метод прогнозирования: для построения прогноза используется последнее значение во временных рядах. В R в пакете fpp2 для построения такого прогноза используется функция naive(). Для построения прогноза берутся не реальные значения показателя, а разницы значений между периодами (рассчитываемые с помощью функции diff()). Так как во временных рядах объемов продаж Superstore наблюдаются и общий тренд, и сезонные колебания, нам потребуется вариация этого метода с учетом сезональности. В методе Naive для прогноза временных рядов с сезонными колебаниями используется соответствующее прошлогоднее значение показателя. Для этого мы будем использовать функцию snaive(). У данной функции есть аргумент h, с помощью которого задается количество прогнозируемых значений. В результате функции создается объект класса forecast, описание которого доступно с помощью функции summary(), а визуализация — с помощью функции autoplot().

# Difference in sales month-by-month
diffSales <- diff(Sales)
# Forecast with Naive method
SalesForecastNaive <- snaive(diffSales) # Residual SD: 18222.875
summary(SalesForecastNaive)
checkresiduals(SalesForecastNaive) # p-value = 0.02341 and left skewed

Из описания модели видно, что сумма отклонений прогнозных значений от реальных значений (Residual sd) равна 18222.875. Значение p-value теста Ljung-Box ниже 0.05, что говорит об отсутствии белого шума в остатках. Распределение остатков смещено влево и не является нормальным.

Следующий метод — метод экспоненциального сглаживания. Прогнозные значения при данном методе являются взвешенными средними предыдущих значений показателя. При этом вес значений показателя убывает с давностью наблюдения, т.е. значения прошлого года будут иметь больший вес, чем значения четыре года назад. Чем новее наблюдение, тем больший вес оно будет иметь в построении прогноза. В Tableau в функции Forecast используется именно метод экспоненциального сглаживания.

Для построения прогноза методом экспоненциального сглаживания в R мы будем использовать функцию ets(). Преимущество данной функции в том, что она попробует все возможные варианты модели экспоненциального сглаживания и вернет лучшую модель. Также в качестве временных рядов здесь используются реальные значения.

# Forecast with Exponential smoothing method
SalesForecastETS <- ets(Sales) # Residual SD: 11261.2
summary(SalesForecastETS)
checkresiduals(SalesForecastETS) # p-value = 0.000106 and normally distributed

Сумма отклонений прогнозных значений от реальных значений (Residual sd) равна 11261.2. Значение p-value теста Ljung-Box ниже 0.05, что говорит об отсутствии белого шума в остатках. Распределение остатков выглядит нормальным.

Следующий метод — ARIMA, который основан на анализе автокорреляции во временных рядах. Метод использует стационарные временные ряды без тренда, т.е. разницы значений показателя между периодами. Разницу при этом не обязательно считать отдельно: можно задать аргумент d=1 функции auto.arima(), которую мы будем использовать для расчета модели. Функция также имеет другие аргументы для ускорения расчетов (approximation, stepwise, trace).

# Forecast with ARIMA method
SalesForecastARIMA <- auto.arima(Sales, d=1, D=1, 
                                 stepwise = FALSE, approximation = FALSE, 
                                 trace = TRUE) # Residual SD: 11337.32
summary(SalesForecastARIMA)
checkresiduals(SalesForecastARIMA) # p-value = 0.1166 and normally distributed

Сумма отклонений прогнозных значений от реальных значений (Residual sd) равна 11337.32. Значение p-value теста Ljung-Box выше 0.05, что говорит о наличии белого шума в остатках. Распределение остатков выглядит нормальным. Наличие белого шума в остатках — это признак хорошего прогноза (отсутствует корреляция между остатками).

Так как модель ARIMA — это единственная модель из рассмотренных, удовлетворяющая требованиям для остатков, ее мы и будем использовать для построения прогноза на следующий год. Прогноз строится с помощью функции forecast() и визуализируется с помощью autoplot().

# Inspecting forecast
SalesForecast <- forecast(SalesForecastARIMA, h = 12)
summary(SalesForecast)

# Plotting the forecast from ARIMA model
options(scipen=10000)
autoplot(SalesForecast) + 
  ggtitle("Forecast for Sales by month for 2020") +
  theme(plot.title = element_text(hjust = 0.5)) + xlab("")

Линия прогноза (point forecast) — это среднее значение показателя по месяцам из возможных значений в будущем. Более темная синяя зона, окружающая линию прогноза, — это 80% доверительный интервал, а более светлая голубая зона — это 95% доверительный интервал.

Далее экспортируем прогноз в csv и построим линейный график продаж с прогнозом в Tableau.

# Converting time series objects to data frames
library(zoo)
pointForecast <- data.frame(Sales = as.matrix(SalesForecast$mean), 
                              Date = as.Date(as.yearmon(time(SalesForecast$mean))))
SalesOriginal <- data.frame(Sales = as.matrix(Sales), 
                              Date = as.Date(as.yearmon(time(Sales))))

# Combining forecast and Sales data frames into one data frame
library(gdata)
SalesAll <- combine(SalesOriginal, pointForecast)

#Exporting to a csv file
write.csv(SalesAll,'Sales.csv', row.names = FALSE)

https://maryiamaziuk.com/data-viz-blog/

Комментирование и размещение ссылок запрещено.

Комментарии закрыты.

63 queries in 0,404 seconds