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. Гэты фармат па сэнсе падобны да UNIXTIME, і захоўвае ў сабе колькасць секунд з моманту пачатку эры 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, то для іх канвертацыі ў зразумелую, чытэльную дату выкарыстоўвайце наступны прыклад:
# Конвертируем 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, месяц, 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 па 29 верасня.
# получить месяц отстающий на 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 у вырашэнні сваіх паўсядзённых задач.