Любой временной ряд по определению представляет собой набор упорядоченных во времени значений некоторой переменной. Поэтому, как и в случае с другими совокупностями, мы можем компактно охарактеризовать свойства временного ряда с помощью предназначенных для этого показателей описательной статистики (среднее значение, медиана, дисперсия, стандартное отклонение, квантили и т.п.). Поскольку наблюдения во временных рядах упорядочены, для них можно рассчитать также и многие специфические показатели, такие как автокорреляция, выраженность тренда и сезонной составляющей, стационарность ряда и т.п.
Помимо того, что описательные статистики временных рядов представляют интерес сами по себе, их используют также в качестве признаков, или предикторов, при создании предсказательных моделей и в других задачах, решаемых с помощью методов машинного обучения (например, кластеризация, выявление аномалий и т.п.). Извлечение таких признаков из временных рядов с помощью R не составляет труда - для этого вполне подойдут как базовые функции, так и функции из многочисленных дополнительных пакетов. Однако учитывая то, как часто возникает необходимость в подобных вычислениях, в идеале было бы удобно иметь один-два пакета, в которых реализован соответствующий функционал. К счастью, такие пакеты для R есть. Одному из них - feasts - посвящено это сообщение.
Инсталляция пакета feasts
Пакет feasts можно установить обычным образом из хранилища CRAN:
install.packages("feasts")
Данные, используемые в примерах
В приведенных ниже примерах использованы данные по стоимости 22 различных криптовалют на момент закрытия торгов в период с 1 января 2018 г. по 6 декабря 2019 г. Структура этого набора данных была описана в предыдущем сообщении. Файл с данными, а также код для воспроизведения примеров можно найти в репозитории ranalytics/feasts_intro. Ниже приведены команды, которые загружают данные в R и выводят сводку по их структуре:
require(readr)
require(dplyr)
require(feasts)
require(tsibble)
require(ggplot2)
require(gridExtra)
require(ggrepel)
# Загрузка данных:
dat <- read_csv("data/cypto_coins.csv") %>%
as_tsibble(., key = coin, index = ds) %>%
mutate(y = log(y))
glimpse(dat)
## Observations: 15,510
## Variables: 3
## Key: coin [22]
## $ y 4.310531, 4.375380, 4.349891, 4.300003, 4.2...
## $ ds 2018-01-01, 2018-01-02, 2018-01-03, 2018-0...
## $ coin "augur", "augur", "augur", "augur", "augur"...
Общее описание пакета feasts
Пакет feasts (от "feature extraction and statistics for time series") представляет собой коллекцию функций, предназначенных для визуализации временных рядов и расчета целого набора показателей, обобщающих их свойства. Подобно рассмотренному ранее пакету tsibble, feasts разработан в соответствии с принципами анализа "опрятных данных" (tidy data), что помимо простого и удобного синтаксиса команд, делает его масштабируемым для одновременной обработки большого количества временных рядов. В этом сообщении мы сконцентрируемся на возможностях feasts по извлечению признаков из временных рядов. Примеры визуализации данных можно найти в официальной документации по этому пакету.Функция features()
В пакете feasts извлечение признаков из временных рядов выполняется с помощью функции-менеджера features(), которая имеет следующие аргументы:- .tbl - таблица с данными (например, объект класса data.frame, tibble, или tsibble);
- .var - имя переменной в таблице .tbl, по значениям которой необходимо вычислить те или иные признаки;
- features - список функций, которые непосредственно выполняют вычисления соответствующих признаков;
- ... - дополнительные аргументы, которые необходимо подать на функции, перечисленные в списке features. Важно отметить, что такие аргументы будут переданы на ту или иную функцию только, если они входят в состав формальных аргументов этой функции, а не являются ее дополнительными аргументами (...). Например, в случае с базовой функцией var(), указание аргумента na.rm = TRUE сработает, поскольку это формальный аргумент var(). В то же время в случае с базовой функцией mean() это не сработает, поскольку na.rm является ее дополнительным аргументом. Чтобы убедиться, что необходимые аргументы будут поданы на нужную функцию, ее следует добавить в список features в виде анонимной функции, как показано в следующем примере:
# Неправильный способ подать дополнительный аргумент на функцию,
# которая вычисляет тот или иной признак (здесь - среднее значение) -
# при наличии пропущенных наблюдений (NA) эта команда не
# выполнила бы расчет среднего:
## features(dat, y, features = list(mean), na.rm = TRUE)
# Правильный способ с использованием анонимной функции:
features(dat, y, features = list(~ mean(., na.rm = TRUE)))
## # A tibble: 22 x 2
## coin V1
## <chr> <dbl>
## 1 augur 2.92
## 2 bitcoin 8.86
## 3 cardano -2.39
## 4 chainlink -0.440
## 5 dash 5.09
## 6 decred 3.54
## 7 dogecoin -5.75
## 8 eos 1.66
## 9 ethereum 5.59
## 10 iota -0.605
## # ... with 12 more rows
Обратите внимание: в последней команде у нас не было необходимости сначала сгруппировать данные по переменной coin - расчет средних значений для отдельных уровней этой переменной был выполнен автоматически. Такой результат стал возможным благодаря тому, что таблица dat является объектом класса tsibble, в котором "ключом" служит переменная coin (см. выше). Функции пакета feasts "знают" как работать с подобными объектами.
Другой момент, на который стоит обратить внимание: результатом выполнения последней команды стала таблица, в которой рассчитанная новая переменная имеет мало о чем говорящее название V1. Чтобы изменить такое поведение feasts, рекомендуется сначала сохранить определение анонимной функции в виде полноценной пользовательской функции. Эта функция должна возвращать вектор с одним или несколькими поименованными элементами - их имена в итоге станут именами соответствующих переменных в таблице с результатами вычислений. В приведенном ниже примере пользовательская функция my_func(x) возвращает вектор со значениями арифметического среднего и дисперсии x:
Другой момент, на который стоит обратить внимание: результатом выполнения последней команды стала таблица, в которой рассчитанная новая переменная имеет мало о чем говорящее название V1. Чтобы изменить такое поведение feasts, рекомендуется сначала сохранить определение анонимной функции в виде полноценной пользовательской функции. Эта функция должна возвращать вектор с одним или несколькими поименованными элементами - их имена в итоге станут именами соответствующих переменных в таблице с результатами вычислений. В приведенном ниже примере пользовательская функция my_func(x) возвращает вектор со значениями арифметического среднего и дисперсии x:
my_func <- function(x) {
m <- mean(x, na.rm = TRUE)
v <- var(x, na.rm = TRUE)
return(c(avg = m, var = v))
}
features(dat, y, features = list(~ my_func(.)))
## # A tibble: 22 x 3
## coin avg var
## <chr> <dbl> <dbl>
## 1 augur 2.92 0.410
## 2 bitcoin 8.86 0.135
## 3 cardano -2.39 0.651
## 4 chainlink -0.440 0.696
## 5 dash 5.09 0.560
## 6 decred 3.54 0.364
## 7 dogecoin -5.75 0.156
## 8 eos 1.66 0.271
## 9 ethereum 5.59 0.436
## 10 iota -0.605 0.617
# ... with 12 more rows
Встроенные функции для расчета признаков
Помимо пользовательских функций, подаваемых на features(), мы можем воспользоваться также целым рядом функций, уже включенных в состав пакета feasts. Например, для расчета коэффициента Xёрста и спектральной энтропии ряда служат функции coef_hurst() и feat_spectral():
Некоторые встроенные в feasts функции возвращают сразу несколько признаков. Например, feat_stl() выполняет разложение временного ряда на компоненты (тренд, сезонная составляющая и остатки) и далее на их основе вычисляет семь различных показателей, включая выраженность тренда ("trend strength"), выраженность сезонной составляющей ("seasonal strength"), линейность ("linearity") и кривизну ("curvature") ряда и т.д. (Hyndman and Athanasopoulos 2019; Kang et al. 2017):
Всего с помощью пакета feasts можно рассчитать 42 признака, характеризующих свойства временных рядов. Для одновременного расчета всех этих признаков можно воспользоваться вспомогательной функцией feature_set() из пакета fabletools (этот пакет устанавливается и загружается вместе с feast автоматически) следующим образом:
Функция feature_set() имеет два аргумента: pkgs - вектор с названиями пакетов, функции из которых вычисляют те или иные признаки, и tags - вектор с "метками", обозначающими группы тематически сходных признаков. В приведенной выше команде мы запросили вычисление всех признаков, реализованных в пакете feasts (feature_set(pkgs = "feasts")). Однако часто более удобным и гибким подходом для формирования списка признаков будет использование аргумента tags. Например, команда feature_set(tags = c("stl", "spectral")) приведет к вычислению всех признаков, возвращаемых функциями feat_stl() и feat_spectral() (см. выше). Список меток всех признаков, реализованных в пакете feasts, можно просмотреть с помощью команды ?features_by_tag. Этот список и краткие пояснения к нему приведены ниже (названия меток выделены жирным шрифтом; после названия каждой метки идут краткое пояснение и список функций, непосредственно выполняющих соответствующие вычисления):
dat %>% features(., y, list(coef_hurst, feat_spectral))
## # A tibble: 22 x 3
## coin coef_hurst spectral_entropy
## <chr> <dbl> <dbl>
## 1 augur 1.000 0.419
## 2 bitcoin 1.000 0.422
## 3 cardano 1.000 0.403
## 4 chainlink 1.000 0.411
## 5 dash 1.000 0.390
## 6 decred 1.000 0.403
## 7 dogecoin 1.000 0.530
## 8 eos 1.000 0.460
## 9 ethereum 1.000 0.398
## 10 iota 1.000 0.386
## # ... with 12 more rows
Некоторые встроенные в feasts функции возвращают сразу несколько признаков. Например, feat_stl() выполняет разложение временного ряда на компоненты (тренд, сезонная составляющая и остатки) и далее на их основе вычисляет семь различных показателей, включая выраженность тренда ("trend strength"), выраженность сезонной составляющей ("seasonal strength"), линейность ("linearity") и кривизну ("curvature") ряда и т.д. (Hyndman and Athanasopoulos 2019; Kang et al. 2017):
dat %>%
features(., y, list(feat_stl)) %>%
glimpse()
## Observations: 22
## Variables: 8
## $ coin <chr> "augur", "bitcoin", "cardano", "chainli...
## $ trend_strength <dbl> 0.9953406, 0.9942791, 0.9972543, 0.9962...
## $ seasonal_strength_week <dbl> 0.1404667, 0.1656911, 0.1708279, 0.1745...
## $ spikiness <dbl> 3.224176e-11, 4.924252e-12, 2.493851e-1...
## $ linearity <dbl> -13.18726277, -0.52454242, -17.47140818...
## $ curvature <dbl> 5.71889415, 7.11470676, 8.39923784, 12....
## $ seasonal_peak_week <dbl> 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, ...
## $ seasonal_trough_week <dbl> 3, 2, 2, 3, 2, 4, 2, 2, 3, 3, 1, 2, 2, ...
Всего с помощью пакета feasts можно рассчитать 42 признака, характеризующих свойства временных рядов. Для одновременного расчета всех этих признаков можно воспользоваться вспомогательной функцией feature_set() из пакета fabletools (этот пакет устанавливается и загружается вместе с feast автоматически) следующим образом:
dat %>%
features(., y, feature_set(pkgs = "feasts")) %>%
glimpse()
## Observations: 22
## Variables: 43
## $ coin <chr> "augur", "bitcoin", "cardano", "chainli...
## $ trend_strength <dbl> 0.9953406, 0.9942791, 0.9972543, 0.9962...
## $ seasonal_strength_week <dbl> 0.1404667, 0.1656911, 0.1708279, 0.1745...
## $ spikiness <dbl> 3.224176e-11, 4.924252e-12, 2.493851e-1...
## $ linearity <dbl> -13.18726277, -0.52454242, -17.47140818...
## $ curvature <dbl> 5.71889415, 7.11470676, 8.39923784, 12....
## $ seasonal_peak_week <dbl> 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, ...
## $ seasonal_trough_week <dbl> 3, 2, 2, 3, 2, 4, 2, 2, 3, 3, 1, 2, 2, ...
## $ acf1 <dbl> 0.9914556, 0.9918121, 0.9917205, 0.9945...
## $ acf10 <dbl> 9.069945, 8.998356, 8.985582, 9.369853,...
## $ diff1_acf1 <dbl> -0.044741822, -0.024806189, -0.00363185...
## $ diff1_acf10 <dbl> 0.021635354, 0.019865632, 0.005004015, ...
## $ diff2_acf1 <dbl> -0.5460928, -0.5321035, -0.5148761, -0....
## $ diff2_acf10 <dbl> 0.3218872, 0.3136450, 0.2758801, 0.2884...
## $ season_acf1 <dbl> 0.9392175, 0.9325213, 0.9318532, 0.9587...
## $ pacf5 <dbl> 0.9850343, 0.9891137, 0.9968590, 0.9968...
## $ diff1_pacf5 <dbl> 0.013912513, 0.010378775, 0.004621421, ...
## $ diff2_pacf5 <dbl> 0.5543664, 0.5463941, 0.5374922, 0.5470...
## $ season_pacf <dbl> -0.0365575838, -0.0026967726, -0.013037...
## $ lambda_guerrero <dbl> 0.6660052, -0.9999242, 1.9999242, 1.060...
## $ kpss_stat <dbl> 6.3481983, 1.8572807, 7.0530723, 6.3001...
## $ kpss_pvalue <dbl> 0.01000000, 0.01000000, 0.01000000, 0.0...
## $ pp_stat <dbl> -2.0541091, -2.0365267, -2.3774878, -0....
## $ pp_pvalue <dbl> 0.10000000, 0.10000000, 0.10000000, 0.1...
## $ ndiffs <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ...
## $ nsdiffs <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...
## $ bp_stat <dbl> 693.0039, 693.5023, 693.3742, 697.2690,...
## $ bp_pvalue <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...
## $ lb_stat <dbl> 695.9571, 696.4576, 696.3289, 700.2403,...
## $ lb_pvalue <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...
## $ var_tiled_var <dbl> 3.673923e-04, 3.213019e-04, 8.631425e-0...
## $ var_tiled_mean <dbl> 0.9975735, 0.9926707, 1.0028359, 1.0017...
## $ shift_level_max <dbl> 0.52872958, 0.29398952, 0.46006865, 0.5...
## $ shift_level_index <dbl> 381, 32, 32, 544, 323, 323, 243, 114, 3...
## $ shift_var_max <dbl> 0.0770071432, 0.0166060677, 0.038770538...
## $ shift_var_index <dbl> 378, 30, 28, 547, 355, 30, 239, 342, 24...
## $ shift_kl_max <dbl> 2.9969862, 2.4043094, 0.6662430, 1.4572...
## $ shift_kl_index <dbl> 380, 322, 31, 543, 238, 322, 242, 113, ...
## $ spectral_entropy <dbl> 0.4186796, 0.4223813, 0.4034126, 0.4106...
## $ n_crossing_points <int> 11, 22, 13, 32, 17, 15, 25, 23, 19, 13,...
## $ n_flat_spots <int> 62, 39, 54, 43, 61, 29, 84, 53, 61, 95,...
## $ coef_hurst <dbl> 0.9998142, 0.9997277, 0.9998600, 0.9997...
## $ stat_arch_lm <dbl> 0.9636507, 0.9632736, 0.9834204, 0.9751...
Функция feature_set() имеет два аргумента: pkgs - вектор с названиями пакетов, функции из которых вычисляют те или иные признаки, и tags - вектор с "метками", обозначающими группы тематически сходных признаков. В приведенной выше команде мы запросили вычисление всех признаков, реализованных в пакете feasts (feature_set(pkgs = "feasts")). Однако часто более удобным и гибким подходом для формирования списка признаков будет использование аргумента tags. Например, команда feature_set(tags = c("stl", "spectral")) приведет к вычислению всех признаков, возвращаемых функциями feat_stl() и feat_spectral() (см. выше). Список меток всех признаков, реализованных в пакете feasts, можно просмотреть с помощью команды ?features_by_tag. Этот список и краткие пояснения к нему приведены ниже (названия меток выделены жирным шрифтом; после названия каждой метки идут краткое пояснение и список функций, непосредственно выполняющих соответствующие вычисления):
acf
Набор признаков, рассчитываемых на основе коэффициентов автокорреляции.- feat_acf()
autocorrelation
Набор признаков, рассчитываемых на основе коэффициентов автокорреляции и частных коэффициентов автокорреляции.- feat_acf()
- feat_pacf()
boxcox
Оптимальное значение параметра \(\lambda\) для преобразования Бокса-Кокса.- guerrero()
coefficients
- coef_hurst()
count
Счетные признаки: количество раз, когда временной ряд пересекает линию, соответствующую медиане всех его значений, и максимальная длина временного отрезка, в пределах которого значения ряда принадлежат к одному из децилей.
- n_crossing_points()
- n_flat_points()
decomposition
Признаки, рассчитываемые на основе компонент временного ряда.
- feat_stl()
lumpiness
Дисперсия дисперсий, рассчитанных по наблюдениям из непересекающихся временных отрезков (окон).
- var_tiled_var()
optimisation
То же, что и метка boxcox выше, т.е. оптимальное значение параметра \(\lambda\) для преобразования Бокса-Кокса.
- guerrero()
pacf
Набор признаков, рассчитываемых на основе частных коэффициентов автокорреляции.
- feat_pacf()
portmanteau
Статистики, рассчитываемые в результате применения тестов Льюнг-Бокса и Бокса-Пирса на наличие автокорреляции в данных.
- box_pierce()
- ljung_box()
rle
Максимальная длина временного отрезка, в пределах которого значения ряда принадлежат к одному из децилей.
- n_flat_spots()
roll
Признаки, рассчитываемые по данным из пересекающихся временных отрезков (окон), в частности максимальный сдвиг среднего уровня, дисперсии, и расстояния Кульбака-Лейблера в следующих друг за другом отрезках.
- shift_level_max()
- shift_var_max()
- shift_kl_max()
seasonal
Признаки, рассчитываемые на основе компонент временного ряда, а также минимальное число дифференцирований ряда, необходимое для достижения его стационарности.
- feat_stl()
- unitroot_nsdiffs()
slide
То же, что и метка roll (см. выше).
spectral
Спектральная энтропия ряда.
- feat_spectral()
stability
Максимальный сдвиг среднего уровня, рассчитанного по данным из двух пересекающихся временных отрезков (окон).
- var_tiled_mean()
stl
Признаки, рассчитываемые на основе компонент временного ряда.
- feat_stl()
test
Статистики, рассчитываемые в ходе различных тестов (на наличие автокорреляции, единичного корня, авторегрессионной условной гетероскедастичности и др.).
- unitroot_kpss()
- unitroot_pp()
- unitroot_ndiffs()
- unitroot_nsdiffs()
- box_pierce()
- ljung_box()
- stat_arch_lm()
tile
Признаки, рассчитываемые по данным из непересекающихся временных отрезков (окон), в частности дисперсия дисперсий и дисперсия средних значений.
- var_tile_mean()
- var_tile_var()
trend
То же, что и метка stl.
unitroot
Статистики, рассчитываемые в ходе тестов на наличие в данных единичного корня, а также минимальное число дифференцирований ряда, необходимое для достижения его стационарности.
- unitroot_kpss()
- unitroot_pp()
- unitroot_ndiffs()
- unitroot_nsdiffs()
Пользовательские функции можно сделать "видимыми" для feature_set() путем их регистрации с помощью вспомогательной функции register_feature():
Другой вопрос, на который было бы интересно ответить: какие ряды необычны по сочетанию нескольких признаков одновременно? Посмотрим, например, как выглядит распределение анализируемых рядов по выраженности тренда и пиков (рис. 2):
На рис. 2 хорошо видны два особенно необычных временных ряда - tether и tron. Мы уже видели, как выглядит ряд tether (см. рис. 1). Изобразим теперь и данные по криптовалюте tron, которая характеризуется как необычно высокой выраженностью тренда, так наличием большого числа (локальных) пиков:
Мы можем пойти еще дальше и проанализировать наши временные ряды с помощью метода главных компонент (PCA) по всем признакам, реализованным в пакете feasts:
Как видно из приведенного результата, первые две главные компоненты объясняют 67.7% всей дисперсии в данных. Изобразим наши временные ряды в системе координат, образованной этими двумя главными компонентами:
Анализ с использованием PCA еще раз подтвердил аномальность временного ряда tether - в данном случае по совокупности 40 признаков. Следует отметить, что этот анализ был выполнен в демонстрационных целях: необычность ряда tether легко заметить и без применения PCA - достаточно изобразить все имеющиеся временные ряды на одном графике (см., например, рис. 1-2 в предыдущем сообщении, где этот ряд выглядит практически как горизонтальная линия). Тем не менее, во многих реальных ситуациях аналитикам приходится иметь дело с сотнями и даже тысячами временных рядов, простой визуальный анализ которых невозможен. Описанный выше подход (возможно, в сочетании с определенным методом обнаружения аномалий), помог бы выявить необычные временные ряды в автоматическом режиме.
В качестве последнего примера, воспользуемся вычисленными нами главными компонентами и выполним кластеризацию временных рядов с помощью метода k средних. Из рис. 4 видно, что анализируемые ряды образуют примерно 4 группы (включая кластер, в который входит только криптовалюта tether). Выполним кластеризацию с k = 4 на основе первых 9 главных компонент, которые в совокупности объясняют более 95% всей дисперии в данных (см. выше):
Изобразим теперь исходные временные ряды, сгруппировав их в соответствии с результатами кластерного анализа:
Пользуясь случаем, хочу поздравить всех читателей с наступающим Новым Годом. Спасибо за вашу поддержку и часто звучащие добрые отзывы - они очень мотивируют и помогают мне продолжать писать, несмотря на мою сумасшедшую занятость. Добра и мира вам и вашим близким!
register_feature(my_func, tags = c("avg_and_var"))
dat %>%
features(., y, feature_set(tags = "avg_and_var")) %>%
glimpse()
## Observations: 22
## Variables: 3
## $ coin <chr> "augur", "bitcoin", "cardano", "chainlink", "dash", "de...
## $ avg <dbl> 2.915508716, 8.857599080, -2.393841413, -0.439869787, 5...
## $ var <dbl> 4.102797e-01, 1.352812e-01, 6.509961e-01, 6.961281e-01,...
Использование признаков, извлеченных из временных рядов
Рассчитанные описанными выше способами признаки позволяют проанализировать и понять свойства сразу нескольких временных рядов. Представим, например, что перед нами стоит задача выявить временные ряды с наибольшей и с наименьшей выраженностью тренда. Это можно было бы сделать следующим образом (рис. 1):
dat_trend <- dat %>%
features(., y, feature_set(tags = "stl"))
min_trend <- dat_trend %>%
filter(trend_strength == min(trend_strength)) %>%
select(coin) %>%
left_join(., dat, by = "coin") %>%
ggplot(., aes(ds, y)) +
geom_line() + facet_grid(~coin) +
theme_bw() +
ggtitle("Минимальный тренд")
max_trend <- dat_trend %>%
filter(trend_strength == max(trend_strength)) %>%
select(coin) %>%
left_join(., dat, by = "coin") %>%
ggplot(., aes(ds, y)) +
geom_line() + facet_grid(~coin) +
theme_bw() +
ggtitle("Максимальный тренд")
grid.arrange(min_trend, max_trend, ncol = 2)
Рис. 1 |
dat_trend %>%
ggplot(., aes(trend_strength, spikiness, label = coin)) +
geom_point() +
ggrepel::geom_text_repel(force = 10) +
theme_bw()
Рис. 2 |
На рис. 2 хорошо видны два особенно необычных временных ряда - tether и tron. Мы уже видели, как выглядит ряд tether (см. рис. 1). Изобразим теперь и данные по криптовалюте tron, которая характеризуется как необычно высокой выраженностью тренда, так наличием большого числа (локальных) пиков:
Рис. 3 |
all_features <- dat %>%
features(., y, feature_set(pkgs = "feasts"))
# Обратите внимание: признаки, в названии которых есть "_pvalue"
# или "diffs" удалены в связи тем, что их дисперсия равна нулю:
pc <- all_features %>%
select(-coin, -contains("_pvalue"),
-contains("diffs")) %>%
prcomp(scale = TRUE)
summary(pc)
## Importance of components:
## PC1 PC2 PC3 PC4 PC5 PC6
## Standard deviation 4.4724 2.0857 1.64528 1.6199 1.21055 1.06671
## Proportion of Variance 0.5556 0.1208 0.07519 0.0729 0.04071 0.03161
## Cumulative Proportion 0.5556 0.6765 0.75166 0.8246 0.86526 0.89686
## PC7 PC8 PC9 PC10 PC11 PC12
## Standard deviation 0.95357 0.84950 0.77343 0.65019 0.5628 0.51481
## Proportion of Variance 0.02526 0.02005 0.01662 0.01174 0.0088 0.00736
## Cumulative Proportion 0.92212 0.94217 0.95879 0.97053 0.9793 0.98669
## PC13 PC14 PC15 PC16 PC17 PC18
## Standard deviation 0.35421 0.33864 0.29528 0.27352 0.16568 0.1470
## Proportion of Variance 0.00349 0.00319 0.00242 0.00208 0.00076 0.0006
## Cumulative Proportion 0.99017 0.99336 0.99578 0.99786 0.99862 0.9992
## PC19 PC20 PC21 PC22
## Standard deviation 0.1337 0.09335 0.03751 1.741e-15
## Proportion of Variance 0.0005 0.00024 0.00004 0.000e+00
## Cumulative Proportion 0.9997 0.99996 1.00000 1.000e+00
Как видно из приведенного результата, первые две главные компоненты объясняют 67.7% всей дисперсии в данных. Изобразим наши временные ряды в системе координат, образованной этими двумя главными компонентами:
pc <- all_features %>%
select(coin) %>%
bind_cols(., as_tibble(pc$x))
pc %>%
ggplot(., aes(PC1, PC2, label = coin)) +
geom_point() +
geom_text_repel(force = 10) +
theme_bw()
Рис. 4 |
В качестве последнего примера, воспользуемся вычисленными нами главными компонентами и выполним кластеризацию временных рядов с помощью метода k средних. Из рис. 4 видно, что анализируемые ряды образуют примерно 4 группы (включая кластер, в который входит только криптовалюта tether). Выполним кластеризацию с k = 4 на основе первых 9 главных компонент, которые в совокупности объясняют более 95% всей дисперии в данных (см. выше):
clust <- pc %>%
select(PC1:PC9) %>%
kmeans(., centers = 4, nstart = 10)
Рис. 5 |
Заключение
В этом сообщении мы рассмотрели особенности работы с пакетом feasts, который позволяет вычислять многие широко используемые описательные признаки временных рядов. Важной особенностью пакета является то, что он был разработан в соответствии с принципами анализа "опрятных данных" - это делает feasts легким в освоении и масштабируемым (т.е. применимым для анализа большого количества временных рядов одновременно). Полученные с помощью feasts описательные признаки можно далее использовать для решения самых разнообразных задач - от "простого" разведочного анализа до автоматического выявления аномальных временных рядов и построения предсказательных моделей.
***
Эта статья завершает цикл публикаций, посвященных временным рядам. В следующем году я планирую уделить много внимания таким "горячим" сегодня темам, как глубокое обучения и работа с большими данными. Не забудьте подписаться на рассылку блога, чтобы не пропустить ничего интересного!Пользуясь случаем, хочу поздравить всех читателей с наступающим Новым Годом. Спасибо за вашу поддержку и часто звучащие добрые отзывы - они очень мотивируют и помогают мне продолжать писать, несмотря на мою сумасшедшую занятость. Добра и мира вам и вашим близким!
Очень приятно видеть что блог живёт, ведь любая информация по R (тем более такого качества как у Вас)для рунета очень ценная.
Ждем новых статей в следующем году!
Хороших праздников:)
Dabavljaju, chto na russkom jaz6ke jest horoshaja kniga na tu zhe temu, s pomoshju kotorovo mozhno imet dopolniteln6je priznaki:
http://www.finstat.ru/katalog/izdatelstvo-fis/optom/statistika/analiz-vremennyx-ryadov-i-prognozirovanie
Jüri Kuusik (https://www.linkedin.com/in/jyrikuusik/)
Планируете ли вы рассмотреть пакет bsts?
Jüri Kuusik
На stackoverflow.com по пишут:
Be sure to enable blog feed
Go to Settings > Others > Site Feed > Allow Blog Feed then select Full
Очень хотелось бы наличие такой возможности. С уважением.
Качество - супер.
И обязательно попробую собрать фичи по моим временным рядам, возможно с кластеризацией и покормлю XGBOOST =)
Отправить комментарий