Робота з датами на мові R (базові можливості, а також пакети lubridate та timeperiodsR)

Отримати поточну дату в будь-якій мові програмування, операція еквівалентна Hello world!. Мова R не є винятком.

У цій статті ми розберемося з тим, як влаштовано роботу з датами в базовому синтаксисі мови R, а також розглянемо кілька корисних пакетів, що розширюють його можливості під час роботи з датами:

  • lubridate — пакет, який дозволяє проводити арифметичні обчислення між датами;
  • timeperiodsR - Пакет для роботи з тимчасовими інтервалами та їх компонентами.

Робота з датами на мові R (базові можливості, а також пакети lubridate та timeperiodsR)

Зміст

Якщо ви цікавитеся аналізом даних, і зокрема мовою R, можливо, вам будуть цікаві мої телеграма и YouTube канали. Більшість контенту яких присвячена мові R.

  1. Робота з датами у базовому синтаксисі R
    1.1. Перетворення тексту на дату
    1.2. Вилучення компонентів дати в базовому R
  2. Робота з датами за допомогою пакету lubridate
    2.1. Перетворення тексту на дату за допомогою lubridate
    2.2. Вилучення компонентів дат за допомогою пакету lubridate
    2.3. Арифметичні операції з датами
  3. Спрощена робота з періодами, пакет timeperiodsR
    3.1. Тимчасові інтервали в timeperiodsR
    3.2. Фільтрування вектора дат за допомогою timeperiodsR
  4. Висновок

Робота з датами у базовому синтаксисі R

Перетворення тексту на дату

У базовому R є набір функцій для роботи з датами. Мінус базового синтаксису полягає в тому, що регістр імен та аргументів функцій дуже розрізнений і практично не має логічного зв'язку. Тим не менш, базові функції мови треба знати, тому ми почнемо саме з них.

Найчастіше під час завантаження даних у R, з csv файлів, чи інших джерел, ви отримуєте дату як тексту. Для того, щоб привести цей текст до правильного типу даних, використовуйте функцію as.Date().

# создаём текстовый вектор с датами
my_dates <- c("2019-09-01", "2019-09-10", "2019-09-23")

# проверяем тип данных
class(my_dates)

#> [1] "character"

# преобразуем текст в дату
my_dates <- as.Date(my_dates)

# проверяем тип данных
class(my_dates)

#> [1] "Date"

За замовчуванням as.Date() приймає дату у двох форматах: РРРР-ММ-ДД або РРРР/ММ/ДД.
Якщо у вашому наборі даних дати представлені в будь-якому іншому форматі, для перетворення можна використовувати аргумент format.

as.Date("September 26, 2019", format = "%B %d, %Y")

формат приймає в рядковому вигляді оператори, що позначають якийсь часовий інтервал і його формат, найбільш часто використовувані значення наведені в таблиці нижче:

Формат
Опис

%d
Номер дня на місяці

%a
Абревіатура назви дня тижня

%A
Повна назва дня тижня

%w
Номер дня тижня (0-6, де 0 ця неділя)

%m
Двозначне позначення місяця (01-12)

%b
Абревіатура імені місяця (apr, mar, …)

%B
Повна назва місяця

%y
Двозначне позначення року

%Y
Чотиризначне позначення року

%j
Номер дня в році (001 - 366)

%U
Номер тижня на рік (00 - 53), початок тижня Неділя

%W
Номер тижня на рік (00 - 53), початок тижня Понеділок

Відповідно, "September 26, 2019" це повна назва місяця, число і рік. Описати цей формат дати операторами можна так:"%B %d, %Y".

Де:

  • %B — Повна назва місяця
  • %d - Номер дня в місяці
  • %Y — Чотиризначне позначення року

При описі формату дати важливо включати всі додаткові символи з вашого рядка, наприклад тире, коми, крапки, пробіли і так далі. У моєму прикладі, "September 26, 2019", після дати стоїть кома, і в опис формату так само треба ставити кому:"%B %d, %Y".

Бувають ситуації, коли ви отримуєте дату не тільки таку, що не відповідає стандартним форматам (РРРР-ММ-ДД або РРРР/ММ/ДД), але ще й мовою, яка відрізняється від встановленого у вашій операційній системі за умовчанням. Наприклад, ви завантажили дані, де дата вказана в такому вигляді: "Грудень 15, 2019 р.". Перед конвертацією цього рядка в дату необхідно змінити локаль.

# Меняем локаль
Sys.setlocale("LC_TIME", "Russian")
# Конвертируем строку в дату
as.Date("Декабрь 15, 2019 г.", format = "%B %d, %Y")

Вилучення компонентів дати в базовому R

У базовому R не так багато функцій, що дозволяють витягувати якусь частину дати з об'єкта класу Дата.

current_date <- Sys.Date() # текущая дата
weekdays(current_date)     # получить номер дня недели
months(current_date)       # получить номер месяца в году
quarters(current_date)     # получить номер квартала в году

Крім основного класу об'єктів Дата в базовому R є ще 2 типи даних, які зберігають позначку часу: POSIXlt, POSIXct. Основна відмінність цих класів від Дата полягає в тому, що, крім дати, вони зберігають час.

# получить текущую дату и время
current_time <- Sys.time()

# узнать класс объекта current_time 
class(current_time)

# "POSIXct" "POSIXt"

Функція Sys.time() повертає поточну дату та час у форматі POSIXct. Цей формат за змістом схожий РОЗВІТ, і зберігає кількість секунд з моменту початку ери UNIX (північ (за UTC) з 31 грудня 1969 року на 1 січня 1970).

клас POSIXlt так само зберігає в собі час і дату, і всі компоненти. Тому є об'єктом з складнішою структурою, але з якого легко отримати будь-який компонент дати і часу. по суті POSIXlt це список.

# Получаем текущую дату и время
current_time_ct <- Sys.time()

# Преобразуем в формат POSIXlt
current_time_lt <- as.POSIXlt(current_time_ct)

# извлекаем компоненты даты и времени
current_time_lt$sec   # секунды
current_time_lt$min   # минуты
current_time_lt$hour  # часы
current_time_lt$mday  # день месяца
current_time_lt$mon   # месяц
current_time_lt$year  # год
current_time_lt$wday  # день недели
current_time_lt$yday  # день года
current_time_lt$zone  # часовой пояс

Перетворення числових та текстових даних у формати POSIX* здійснюються функціями as.POSIXct() и as.POSIXlt(). Ці функції мають невеликий набір аргументів.

  • x — Число, рядок або об'єкт класу Дата, який необхідно перетворити;
  • tz - Часовий пояс, за умовчанням "GMT";
  • format — Опис формату дати, в якому представлені дані, що передаються в аргумент x;
  • origin — Використовується лише при конвертації числа в POSIX, в цей аргумент необхідно передати об'єкт дати, і час від якого йде відлік секунд. Як правило, використовується для перекладу з UNIXTIME.

Якщо ваші дані про дату та час представлені в РОЗВІТ, то для їх конвертації в зрозумілу дату, що читається, використовуйте наступний приклад:

# Конвертируем UNIXTIME в читаемую дату 
as.POSIXlt(1570084639,  origin = "1970-01-01")

В origin ви можете вказати будь-яку мітку. Наприклад, якщо у ваших даних дата та час вказані як кількість секунд, починаючи від 15 вересня 2019 року 12:15, то для перетворення їх на дату використовуйте:

# Конвертируем UNIXTIME в дату учитывая что начало отсчёта 15 сентября 2019 12:15
as.POSIXlt(1546123,  origin = "2019-09-15 12:15:00")

Робота з датами за допомогою пакету lubridate

lubridate мабуть найпопулярніший пакет для роботи з датами R. Він надає вам додатково ще три класи.

  • durations - Тривалість, тобто. кількість секунд між двома тимчасовими мітками;
  • periods - періоди дозволяють проводити обчислення між датами зрозумілими для людини інтервалами: днями, місяцями, тижнями тощо;
  • intervals — об'єкти, що надають початковий та кінцевий момент часу.

Встановлення додаткових пакетів у мові R здійснюється стандартною функцією install.packages().

Встановлення пакету lubridate:

install.packages("lubridate")

Перетворення тексту на дату за допомогою lubridate

Функції пакету lubridate значно спрощують процес конвертації тексту в дату, а також дозволяють вам проводити будь-які арифметичні операції з датами і часом.

Отримати поточну дату або дату та час вам допоможуть функції today() и now().

today() # текущая дата
now()   # текущая дата и время

Для перетворення рядка на дату в lubridate є ціле сімейство функцій, імена яких складаються завжди з трьох букв, і позначають послідовність компонентів дати:

  • y - рік
  • m - місяць
  • d - день

Список функцій для перетворення тексту на дату через lubridate

  • ymd()
  • ydm()
  • mdy()
  • myd()
  • dmy()
  • dym()
  • yq()

Декілька прикладів для перетворення рядків на дати:

ymd("2017 jan 21")
mdy("March 20th, 2019")
dmy("1st april of 2018")

Як бачите lubridate значно ефективніше вміє розпізнавати опис дат як тексту, і дозволяє вам перетворювати текст на дату не використовуючи додаткових операторів для опису формату.

Вилучення компонентів дат за допомогою пакету lubridate

Також за допомогою lubridate можна отримати будь-який компонент з дати:

dt <- ymd("2017 jan 21")

year(dt)  # год
month(dt) # месяц
mday(dt)  # день в месяце
yday(dt)  # день в году
wday(dt)  # день недели

Арифметичні операції з датами

Але, найбільш важливий та основний функціонал lubridate полягає у можливості проводити різні арифметичні операції з датами.

Округлення дати здійснюється трьома функціями:

  • floor_date — округлення до найближчого часу
  • ceiling_date - Округлення до найближчого майбутнього часу
  • round_date - Округлення до найближчого часу

Кожна з цих функцій має аргумент блок, який дозволяє вам вказати одиницю округлення: second, minute, hour, day, week, month, bimonth, quarter, season, halfyear, year

dt <- ymd("2017 jan 21")

round_date(dt, unit = "month")    # округлить до месяца
round_date(dt, unit = "3 month")  # округлить до 3 месяцев
round_date(dt, unit = "quarter")  # округлить до квартала
round_date(dt, unit = "season")   # округлить до сезона
round_date(dt, unit = "halfyear") # округлить до полугодия

Отже, розберемося з тим, як отримати дату, яка буде через 8 днів після поточної дати і проводити різні інші арифметичні обчислення між двома датами.

today() + days(8)   # какая дата будет через 8 дней
today() - months(2) # какая дата была 2 месяца назад
today() + weeks(12) # какая дата будет через 12 недель
today() - years(2)  # какая дата была 2 года назад

Спрощена робота з періодами, пакет timeperiodsR.

timeperiodsR — свіжий пакет для роботи з датами, який був опублікований на CRAN у вересні 2019 року.

Встановлення пакету timeperiodsR:

install.packages("timeperiodsR")

Основне призначення - швидке визначення деякого часового інтервалу щодо заданої дати. Наприклад, за допомогою його функцій ви легко можете:

  • Отримати минулий тиждень, місяць, квартал або рік у R.
  • Отримати задану кількість часових інтервалів щодо дати, наприклад, минулі 4 тижні.
  • Легко витягувати з отриманого часового інтервалу його компоненти: початкову і кінцеву дату, кількість днів, що потрапили в інтервал, всю послідовність дат, які до нього входять.

Назва всіх функцій пакету timeperiodsR інтуїтивно зрозумілі і складаються з двох частин: направлення_інтервал, Де:

  • направлення в якому необхідно рухатися щодо заданої дати: last_n, previous, this, next, next_n.
  • тимчасової інтервал для обчислення періоду: day, week, month, quarter, year.

Повний набір функцій:

  • last_n_days()
  • last_n_weeks()
  • last_n_months()
  • last_n_quarters()
  • last_n_years()
  • previous_week()
  • previous_month()
  • previous_quarter()
  • previous_year()
  • this_week()
  • this_month()
  • this_quarter()
  • this_year()
  • next_week()
  • next_month()
  • next_quarter()
  • next_year()
  • next_n_days()
  • next_n_weeks()
  • next_n_months()
  • next_n_quarters()
  • next_n_years()
  • custom_period()

Тимчасові інтервали в timeperiodsR

Ці функції корисні у випадках, коли вам необхідно робити звіти на основі даних за минулий тиждень або місяць. Щоб отримати минулий місяць, скористайтеся однойменною функцією previous_month():

prmonth <- previous_month()

Після чого у вас буде об'єкт prmonth класу тпр, З якого легко можна отримати наступні компоненти:

  • дату початку періоду, у нашому прикладі це минулий місяць
  • дату завершення періоду
  • кількість днів, що входять у період
  • послідовність дат, що входять у період

Причому отримати кожен із компонентів можна різними способами:

# первый день периода
prmonth$start
start(prmonth)

# последний день периода
prmonth$end
end(prmonth)

# последовательность дат
prmonth$sequence
seq(prmonth)

# количество дней входящих в период
prmonth$length
length(prmonth)

Також ви можете отримати будь-який з компонентів, використовуючи аргумент частина, який є у кожній з функцій пакета. Можливі значення: start, end, sequence, length.

previous_month(part = "start")    # начало периода
previous_month(part = "end")      # конец периода
previous_month(part = "sequence") # последовательность дат
previous_month(part = "length")   # количество дней в периоде

Отже, давайте розглянемо всі аргументи доступні у функціях пакету timeperiodsR:

  • x - Опорна дата від якої обчислюватиме тимчасовий період, за промовчанням поточна дата;
  • n — кількість інтервалів, які входитимуть у період, наприклад, 3 попередні тижні;
  • part - Який компонент об'єкта tpr вам необхідно отримати, за замовчуванням all;
  • week_start — Аргумент присутній тільки у функціях для роботи з тижнями, і дозволяє задати номер дня тижня який вважатиметься його початком, за замовчуванням початком тижня є понеділок, але ви можете задати будь-який з 1 понеділок по 7 неділю.

Таким чином, ви можете обчислювати будь-який тимчасовий період щодо поточної або будь-якої іншої заданої дати, наведу ще кілька прикладів:

# получить 3 прошлые недели
# от 6 октября 2019 года
# начало недели - понедельник
last_n_weeks(x = "2019-10-06", 
             n = 3, 
             week_start = 1)

 Time period: from  9 September of 2019, Monday to 29 September of 2019, Sunday

6 жовтня ця неділя:
Робота з датами на мові R (базові можливості, а також пакети lubridate та timeperiodsR)

Нам необхідний період, який щодо 6 жовтня візьме три попередні тижні. Не включаючи тиждень, до якого входить саме 3 жовтня. Відповідно, це період з 6 по 9 вересня.

Робота з датами на мові R (базові можливості, а також пакети lubridate та timeperiodsR)

# получить месяц отстающий на 4 месяца
# от 16 сентября 2019 года
previous_month(x = "2019-09-16", n = 4)

 Time period: from  1 May of 2019, Wednesday to 31 May of 2019, Friday

У цьому прикладі нас цікавить місяць, який був 4 місяці тому, якщо відштовхуватися від 16 вересня 2019 року, відповідно, це був травень 2019 року.

Фільтрування вектора дат за допомогою timeperiodsR

Для фільтрації дат у timeperiodsR є кілька операторів:

  • %left_out% — порівнює два об'єкти класу tpr, та повертає значення з лівого, які відсутні у правому.
  • %left_in% — порівнює два об'єкти класу tpr, і повертає дати з лівого об'єкта, які входять у правий.
  • %right_out% — порівнює два об'єкти класу tpr і повертає значення з правого, які відсутні у лівому.
  • %right_in% — порівнює два об'єкти класу tpr, і повертає дати з правого об'єкта, які є у лівому.

period1 <- this_month("2019-11-07")
period2 <- previous_week("2019-11-07")

period1 %left_in% period2   # получить даты из period1 которые входят в period2
period1 %left_out% period2  # получить даты из period1 которые не входят в period2
period1 %right_in% period2  # получить даты из period2 которые входят в period1
period1 %right_out% period2 # получить даты из period2 которые не входят в period1

У пакета timeperiodsR є офіційний, російськомовний плейлист на YouTube.

Висновок

Ми детально розглянули класи об'єктів, які призначені в мові R для роботи з датами. Також тепер ви вмієте проводити над датами арифметичні операції, та швидко отримувати будь-які часові періоди за допомогою пакету timeperiodsR.

Якщо вам цікава мова R запрошую вас підписатися на мій телеграм канал R4marketing, в якому я на щоденній основі ділюся корисними матеріалами про застосування мови R у вирішенні своїх повсякденних завдань.

Джерело: habr.com

Додати коментар або відгук