参考:《R数据科学》
使用lubridate处理日期和时间
1 简介
当我们处理一些时间序列数据时,我们经常会遇到各种时间数据,如2016-03-03。大多数时候,我们需要提取年、月、日甚至小时、分、秒,以便于比较和筛选。
1.1 准备工作
lubridate 包,它能做到 R 处理日期和时间更容易。
library(tidyverse) library(lubridate) library(nycflights13)
2 创建日期或时间
在R的相应数据结构中保存日期时间数据
- 日期:在tibble 中显示为
- 时间:一天中的某个时刻,在 tibble 中显示为
- 日期时间:在某一时刻(通常精确到秒),只能标记日期加时间tibble 中显示为
您可以使用当前日期或当前日期 today() 或 now() 函数
以下 3 该方法还可以创建日期或时间。
- 通过字符串创建。
- 创建日期时间的各种成分。
- 创建现有的日期时间对象。
2.1通过字符串创建
lubridate年月日数据提供函数帮助处理不同的排列顺序:
在日期数据中确定年、月、日的顺序,然后按同样的顺序排列 y、m 和 d,这样,就可以组成一个可以分析日期的日期 lubridate 函数名称。
ymd("20110604") #[1] "2011-06-04" mdy("06-04-2011") #[1] "2011-06-04" dmy("04/06/2011") #[1] "2011-06-04" 这些函数也可以接受没有引号的值。

如果你想创建日期时间数据,你可以在后面添加下划线和 h、m 和 s 其中一个或多个字母可以获得分析日期时间的函数
2.2通过各种成分创建
除单个字符串外,日期时间数据的所有成分也经常分布在表格的多个列中。 可以使用 make_date() 函数创建日期,使用 make_datetime() 函数创建日期时间
2.33通过其他类型的数据创建
转换日期时间数据和日期数据, as_datetime() 和 as_date() 函数的功能
3 日期时间成分
3.1获取成分
若要在日期中提取独立成分,可使用以下访问器函数:year()、month()、mday() ( 一 个 月 中 的 第 几 天 )、yday()( 一 年 中 的 第 几 天 )、wday()( 一 周 中 的 第 几 天 )、hour()、minute() 和 second()
1.lubridate函数的便利性在于,无论年、月、日之间有什么间隔符,它总能找到正确的值并返回数字值,例如:
datetime<-ymd_hms("2016-07-08 12:34:56") datetime #[1] "2016-07-08 12:34:56 UTC" year(datetime) #[1] 2016 month(datetime) #[1 ]7 day(datetime) #[1] 8 mday(datetime)#一个月中的第几天 #[1] 8 yday(datetime)#一年中的第几天 #[1] 190 wday(datetime)#一周中的第几天 #[1] 6 hour("2011-08-10 14:20:01") #[1] 14 minute("2011-08-10 14:20:01") #[1] 20 second("2011-08-10 14:20:01") #[1] 1 对于month()和wday()函数,可以设置label = TRUE月名和周数的缩写也可以设置 abbr = FALSE 来返回全名
datetime<-ymd_hms("2016-07-08 12:34:56") datetime #[1] "2016-07-08 12:34:56 UTC" month(datetime,label = T,abbr = T) # [1] 7月 # 12 Levels: 1月 < 2月 < 3月 < 4月 < 5月 < 6月 < 7月 < 8月 < 9月 < ... < 12月 wday(datetime,label = T,abbr = T)#一周中的第几天 # [1] 周五 # Levels: 周日 < 周一 < 周二 < 周三 < 周四 < 周五 < 周六
3.2 舍入
另一种绘制独立日期成分的方法是通过floor_date()、round_date()和ceiling_date()函数将日期放入临近的时间单位。这些函数的参数包括需要调整的时间向量和时间单位的名称。函数将向量舍下、进入或四舍五入此时间单位。例如,以下代码可以绘制每周的航班数量:
3.4设置成分
使用每个访问器函数来设置日期中的组件:
datetime<-ymd_hms("2016-07-08 12:34:56") datetime #[1] "2016-07-08 12:34:56 UTC" year(datetime) <- 2020 datetime #[1] "2020-07-08 12:34:56 UTC" month(datetime) <- 02 datetime #[1] "2020-02-08 12:34:56 UTC" hour(datetime) <- hour(datetime) 1 datetime # [1] "2020-02-08 13:34:56 UTC" 除原地修改外,还可通过原地修改update()函数创建新日期时间。这也可以同时设置多个成分:
dtetime<-ymd_hms("2016-07-08 12:34:56")
datetime
#[1] "2016-07-08 12:34:56 UTC"
update(datetime,year=2020,month=2,mday=22,hour=2)
# [1] "2020-02-22 02:34:56 UTC"
如果设置的值过大,那么可以自动向后滚动:
ymd("2020-02-22")%>%
update(mday=30)
# [1] "2020-03-01"
#今年有2月29
ymd("2020-02-22")%>%
update(hour=400)
# [1] "2020-03-09 16:00:00 UTC"
4 时间间隔
学习如何对日期进行数学运算,其中包括减法、加法和除法。
- 时期: 以秒为单位表示一段精确的时间。
- 阶段: 表示由人工定义的一段时间,如几周或几个月。
- 区间:表示从起点到终点的一段时间。
4.1 时期——总是以秒为单位来记录时间间隔。
如果将两个日期相减
today()-ymd(19970107)
# Time difference of 8446 days
表示时间差别的对象记录时间间隔的单位可以是秒、分钟、小时、日或周。 lubridate 提供了总是使用秒为单位的另一种计时对象——时期
a_date <- today()-ymd(19970107)
as.duration(a_date)
# [1] "729734400s (~23.12 years)"
可以使用很多方便的构造函数来创建时期:
dseconds(15)
#[1] "15s"
dminutes(10)
# [1] "600s (~10 minutes)"
dhours(c(12,24))
# [1] "43200s (~12 hours)" "86400s (~1 days)"
ddays(0:5)
# [1] "0s" "86400s (~1 days)" "172800s (~2 days)"
# [4] "259200s (~3 days)" "345600s (~4 days)" "432000s (~5 days)"
dweeks(3)
# [1] "1814400s (~3 weeks)"
dyears(1)
# 1] "31536000s (~52.14 weeks)"
可以对时期进行加法和乘法操作:
dyears(1)*2
# [1] "63072000s (~2 years)"
dyears(1)+dweeks(1)+ddays(1)
# [1] "32227200s (~1.02 years)"
时期可以和日期型数据相加或相减:
tomorrow<-today()+ddays(1)
tomorrow
# [1] "2020-02-23"
last_year<-today()-dyears(1)
last_year
# [1] "2019-02-22"
4.2 阶段——“人工”时间
lubridate 提供了阶段对象。阶段也是一种时间间隔,但它不以秒为单位;相反,它使用“人工”时间,比如日和月。这使得它们使用起来更加直观:
和时期一样,我们也可以使用很多友好的构造函数来创建阶段:
seconds(15)
# 1] "15S"
minutes(10)
# [1] "10M 0S"
hours(c(12,24))
# [1] "12H 0M 0S" "24H 0M 0S"
days(7)
# [1] "7d 0H 0M 0S"
months(1:3)
# [1] "1m 0d 0H 0M 0S" "2m 0d 0H 0M 0S" "3m 0d 0H 0M 0S"
weeks(1)
# [1] "7d 0H 0M 0S"
years(1)
# [1] "1y 0m 0d 0H 0M 0S"
可以对阶段进行加法和乘法操作:
10*(months(6)+days(1))
# [1] "60m 10d 0H 0M 0S"
days(50)+hours(25)+minutes(2)
# [1] "50d 25H 2M 0S"
阶段可以和日期相加。与时期相比,阶段更容易符合我们的预期:
#闰年
ymd("2016-01-01")+dyears(1)
#[1]"2016-12-31"
ymd("2016-01-01")+years(1)
#[1]"2017-01-01"
4.3 区间
如果需要更精确的测量方式,那么你就必须使用区间。区间是带有起点的时期,这使得其非常精确,你可以确切地知道它的长度
next_year<-today()+years(1)
(today()%--%next_year)/ddays(1)
#[1] 365
4.4 小结
- 如果只关心物理时间,那么就使用时期;
- 如果还需要考虑人工时间,那么就使用阶段;
- 如果需要找出人工时间范围内有多长的时间间隔,那么就使用区间