рекомендации

суббота, 11 апреля 2020 г.

Работа с временными рядами в R с помощью пакетов xts и zoo. Часть 4. Применение функций семейства apply к временным рядам

Перевод. Оригинал: Manipulating Time Series Data in R with xts & zoo

Часть 4. Применение функций семейства apply к временным рядам

Первая часть
Вторая часть
Третья часть

Нахождение интервалов по времени в xts

Одним из преимуществ работы с объектами временных рядов является то, насколько легко применять функции по времени.

Основной функцией в xts для облегчения этих действий является endpoints(). Она принимает временной ряд (или вектор времен) и возвращает местоположения последних наблюдений в каждом интервале.

Например, приведенный ниже код находит последнее наблюдение каждого года для набора данных AirPass.
endpoints(AirPass, on = “years”)

 [1] 0 12 24 36 48 60 72 84 96 108 120 132 144

Аргумент "on" поддерживает различные периоды, включая “years”, “quarters”, “months”, а также внутридневные интервалы, такие как “hours” и “minutes”. Возвращается вектор, начинающийся с 0 и заканчивающийся экстентом (последней строкой) ваших данных.

В дополнение к каждому периоду вы можете найти период KthKth, используя аргумент k. Например, установка аргументов вашего вызова endpoints() в on = «days», k = 2, будет генерировать последний день каждой второй недели в ваших данных. Обратите внимание, что последнее возвращаемое значение всегда будет длиной ваших входных данных, даже если они не соответствуют пропущенному интервалу.

В этом упражнении вы будете использовать endpoints(), чтобы найти два набора конечных точек для ежедневных временных данных.

Инструкции:
Используйте endpoints(), чтобы найти конец недели в ваших временных данных.
Используйте endpoints(), чтобы найти конец каждой второй недели в ваших временных данных. Не забудьте использовать аргумент k.


# Находим последнее наблюдение каждой недели
endpoints(temps, on = "weeks")

# Находим последнее наблюдение каждой второй недели
endpoints(temps, on = "weeks", k = 2)

Как вы увидите в следующем упражнении, определение местоположения конечных точек может помочь ускорить процесс агрегации данных временных рядов.

Применение функций к временным периодам

На данный момент вы знаете, как найти конец периодов, используя endpoints(). Вам может быть интересно, что вы можете делать с этими значениями.

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

Чтобы делать это легко, xts предоставляет команду period.apply(), которая принимает временной ряд, индекс конечных точек и функцию.

period.apply (x, INDEX, FUN, ...) 

В этом упражнении вы будете практиковать использование period.apply(), находя среднее значение за неделю из ваших данных temps. Вы также рассмотрите одну из функций shortcut, которая делает то же самое с немного другим синтаксисом.

Инструкции:
Вычислите еженедельные конечные точки ряда temps и сохраните их как ep.
Используя period.apply(), вычислите среднее значение за неделю для столбца Temp.Mean ваших данных temps. Помните, что ваши конечные точки рассчитывались еженедельно.

# Рассчитываем недельные конечные точки
ep <- endpoints(temps, on = "weeks")

# Рассчитываем недельное среднее и выводим результат
period.apply(temps[, "Temp.Mean"], INDEX = ep, FUN = mean)
       Temp.Mean

2016-07-03 67.66667 2016-07-10 76.71429 2016-07-16 77.00000

Команда period.apply() позволяет вам легко вычислять сложные параметры данных вашего временного ряда.

Использование функций lapply() и split() на интервалах

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

В этом упражнении вы будете использовать команду xts split() для разбивки ваших данных по времени. Функция split() создает список, содержащий элемент для каждого разбиения. Аргумент f в split() - это строка символов, описывающая период, по которому нужно разделить данные (то есть “months”, “years” и т. д.).

Здесь вы будете следовать тому же процессу, что и в предыдущем упражнении. Однако на этот раз вы сначала вручную разделите свои данные, а затем примените функцию mean() к каждой части. Функция lapply() используется для повышения эффективности расчетов. В случаях, когда вам не нужно возвращать временные ряды, она оказывается очень интуитивной и эффективной.

Инструкции:
Используйте split(), чтобы разделить ваши временные данные по неделям. Назовите его temps_weekly.
Используйте lapply(), чтобы получить еженедельное среднее значение temps_weekly. Назовите его temps_avg. Выведите этот список.


# Разделяем temps по неделям
temps_weekly <- split(temps, f = "weeks")

# Создаем список недельных средних temps_avg, и выводим его
temps_avg <- lapply(X = temps_weekly, FUN = mean)
temps_avg

Как вы можете видеть, period.apply() аналогично использованию комбинации split() и lapply().

Выборка с помощью endpoints vs. split-lapply-rbind

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

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

Обратите внимание, что эти функции всегда будут находить даты, которые находятся в закрытом интервале [начало периода, конец периода], даже если в начале или в конце интервала нет наблюдения. xts представляет нерегулярные временные ряды, поэтому вполне допустимо иметь дыры в данных.

Найдите последнее наблюдение за каждую неделю в наших временных данных.

Инструкции:
Используйте парадигму split() - lapply() - rbind(), заданную для вас в скрипте, чтобы найти последнее наблюдение в каждой неделе во временном интервале. Сохраните результат в temps_1.
Используйте endpoints(), чтобы найти последние дни недели в temps. Сохраните полученный вектор в last_day_of_weeks.
Создайте temps_2 путем выборки из temp с использованием last_day_of_weeks.


# Используем комбинацию split, lapply и rbind
temps_1 <- do.call(rbind, lapply(split(temps, "weeks"), function(w) last(w, n = "1 day")))

# Создаем last_day_of_weeks, используя endpoints()
last_day_of_weeks <- endpoints(temps, "weeks")

# Делаем выборку из temps, используя last_day_of_weeks 
temps_2 <- temps[last_day_of_weeks]

Конвертирование одномерных рядов в данные OHLC

Агрегирование временных рядов может быть неприятной задачей. Например, в финансовых сериях часто встречаются данные Open-High-Low-Close (или OHLC), рассчитанные для некоторого повторяющегося и регулярного интервала.

Также известное как range bars, агрегирование ряда на основе некоторого обычного окна может упростить анализ среди рядов с разными частотами. Недельный экономический ряд и дневной ряд акций легче сравнивать, если ежедневный конвертировать в недельный.

В этом упражнении вы преобразуете одномерный ряд в ряд OHLC, а затем конвертируете ряд OHLC обратно в одномерный ряд с помощью функции xts to.period(). Эта функция принимает временной ряд, x и строку для периода (например, months, days и т. д.), в дополнение к ряду других необязательных аргументов.

to.period(x, period = “months”, k = 1, indexAt, name=NULL, OHLC = TRUE, …) 

Для этого упражнения вы будете использовать новый набор данных usd_eur, ежедневный курс доллара США к евро с 1999 года по август 2016 года, который загружен в ваше рабочее пространство.

Инструкции:
Преобразуйте usd_eur в недельный ряд OHLC, используя to.period(). Назовите этот новый ряд usd_eur_weekly. Обратите внимание, что по умолчанию OHLC = TRUE.
Конвертируйте usd_eur в ежемесячный ряд OHLC. Назовите этот ряд usd_eur_monthly.
Конвертируйте usd_eur в годичный ряд (без столбцов OHLC). Назовите его usd_eur_yearly.


# Конвертируем usd_eur в недельный ряд и сохраняем в usd_eur_weekly
usd_eur_weekly <- to.period(usd_eur, period = "weeks")

# Конвертируем usd_eur в месячный ряд и сохраняем в usd_eur_monthly
usd_eur_monthly <- to.period(usd_eur, period = "months")

# Конвертируем usd_eur в годовой одномерный ряд и сохраняем в usd_eur_yearly
usd_eur_yearly <- to.period(usd_eur, period = "years", OHLC = FALSE)

Преобразование частоты ряда в более низкую 

Помимо преобразования одномерного временного ряда в ряд OHLC, to.period() также позволяет вам преобразовывать OHLC в более низкую регуляризованную частоту - что-то вроде субдискретизации ваших данных.

В зависимости от выбранной частоты класс индекса ваших данных может быть приведен к чему-то более подходящему для новых данных. Например, при использовании функции быстрого вызова to.quarterly() xts преобразует ваш индекс в класс yearqtr, чтобы сделать периоды более очевидными.

Мы можем переопределить это поведение, используя аргумент indexAt. В частности, использование firstof даст вам время с начала периода. Кроме того, вы можете изменить базовое имя каждого столбца, указав строку в имени аргумента.

Для этого упражнения мы представим новый набор данных, данные индекса хедж-фонда edhec из пакета PerformanceAnalytics.

В этом упражнении вы будете использовать временные ряды Equity Market Neutral из данных edhec, которым мы присвоили имя eq_mkt.

Инструкции:
Преобразуйте eq_mkt в квартальный OHLC с использованием функции to.period(). Назовите результат mkt_quarterly.
Снова преобразуйте исходный eq_mkt, на этот раз с помощью to.quarterly(). Измените базовое имя каждого столбца OHLC на edhec_equity и измените индекс на «firstof». Назовите результат mkt_quarterly2.


install.packages("PerformanceAnalytics")
library(PerformanceAnalytics)
data(edhec)
dim(edhec)
names(edhec)
eq_mkt <- edhec[, "Equity Market Neutral"]
dim(eq_mkt)

# Конвертируем eq_mkt в квартальный OHLC
mkt_quarterly <- to.period(eq_mkt, period = "quarters")

# Конвертируем eq_mkt в квартальный, используя функцию быстрого вызова
mkt_quarterly2 <- to.quarterly(edhec, name = "edhec_quity", indexAt = "firstof")

Расчет базовых скользящих показателей рядов по месяцам

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

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

В этом упражнении вы рассчитаете совокупный годовой доход, используя данные фонда edhec из последнего упражнения. Для этого вы будете следовать шаблону split()-lapply()-rbind (), показанному ниже:

x_split = split(x, f = “months”) 
x_list = lapply(x_split, cummax) 
x_list_rbind = do.call(rbind, x_list) 

Обратите внимание, что последний вызов использует несколько странный синтаксис do.call(rbind, ...) в R, который позволяет вам передавать список в rbind вместо того, чтобы передавать объекты по одному. Это удобный ярлык для вашего набора инструментов R.

Инструкции:
Используя split(), разбейте данные edhec на годы. Сохраните результат как edhec_years.
Используйте lapply(), чтобы найти cumsum() прибылей за год в edhec_years. Сохраните как edhec_ytd.
Используйте do.call() вместе с rbind, чтобы преобразовать предыдущий вывод списка в один объект xts. Сохраните как edhec_xts.


# Делим edhec по годам
edhec_years <- split(edhec , f = "years")

# Используем lapply для расчета cumsum для каждого года в edhec_years
edhec_ytd <- lapply(edhec_years, FUN = cumsum)

# Используем do.call для объединения результатов
edhec_xts <- do.call(rbind, edhec_ytd)

Расчет скользящего стандартного отклонения временного ряда

Другим распространенным требованием при работе с данными временных рядов является применение функции к скользящему окну данных. xts предоставляет эту возможность с помощью интуитивно названной функции zoo rollapply().

Эта функция принимает объект временного ряда x, ширину окна и функцию FUN для применения к каждому скользящему периоду. Аргумент width может быть хитрым; число, указанное в аргументе width, указывает количество наблюдений в окне. Например, чтобы взять 10-дневный максимум ряда, вы должны ввести следующее:

rollapply(x, width = 10, FUN = max, na.rm = TRUE) 

Обратите внимание, что вышеприведенный код рассчитает 10-дневный максимум только для ряда с ежедневными наблюдениями. Если бы в ряду были ежемесячные наблюдения, то вы получили бы максимум за 10 месяцев. Также обратите внимание, что вы можете передавать дополнительные аргументы (то есть na.rm в функцию max) так же, как и в apply().

Инструкции:
Используя rollapply(), рассчитайте 3-месячное стандартное отклонение ряда eq_mkt. Обратите внимание, что eq_mkt включает ежемесячные наблюдения. Назовите свое 3-месячное скользящее стандартное отклонение eq_sd.


# Используем rollapply для расчета скользящего 3-периодного sd от eq_mkt
eq_sd <- rollapply(eq_mkt, width=3, FUN = sd)

Скользящие значения являются полезным показателем в данных временных рядов. Теперь, когда вы знакомы с основными функциями пакета xts, в последней главе будут рассмотрены несколько более сложных тем, использующих xts.

 Набор данных temps 

Temp.Max Temp.Mean Temp.Min 
2016-07-01 74 69 60 
2016-07-02 78 66 56 
2016-07-03 79 68 59 
2016-07-04 80 76 69 
2016-07-05 90 79 68 
2016-07-06 89 79 70 
2016-07-07 87 78 72 
2016-07-08 89 80 72 
2016-07-09 81 73 67 
2016-07-10 83 72 64 
2016-07-11 93 81 69 
2016-07-12 89 82 77 
2016-07-13 86 78 68 
2016-07-14 89 80 68 
2016-07-15 75 72 60 
2016-07-16 79 69 60

Комментариев нет:

Отправить комментарий