ProHoster > Блог > адміністрування > Робота з датами на мові R (базові можливості, а також пакети lubridate та timeperiodsR)
Робота з датами на мові R (базові можливості, а також пакети lubridate та timeperiodsR)
Отримати поточну дату в будь-якій мові програмування, операція еквівалентна Hello world!. Мова R не є винятком.
У цій статті ми розберемося з тим, як влаштовано роботу з датами в базовому синтаксисі мови R, а також розглянемо кілька корисних пакетів, що розширюють його можливості під час роботи з датами:
lubridate — пакет, який дозволяє проводити арифметичні обчислення між датами;
timeperiodsR - Пакет для роботи з тимчасовими інтервалами та їх компонентами.
Зміст
Якщо ви цікавитеся аналізом даних, і зокрема мовою R, можливо, вам будуть цікаві мої телеграма и YouTube канали. Більшість контенту яких присвячена мові 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 жовтня ця неділя:
Нам необхідний період, який щодо 6 жовтня візьме три попередні тижні. Не включаючи тиждень, до якого входить саме 3 жовтня. Відповідно, це період з 6 по 9 вересня.
# получить месяц отстающий на 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
Ми детально розглянули класи об'єктів, які призначені в мові R для роботи з датами. Також тепер ви вмієте проводити над датами арифметичні операції, та швидко отримувати будь-які часові періоди за допомогою пакету timeperiodsR.
Якщо вам цікава мова R запрошую вас підписатися на мій телеграм канал R4marketing, в якому я на щоденній основі ділюся корисними матеріалами про застосування мови R у вирішенні своїх повсякденних завдань.