R语言基础入门(8)之日期时间
目录
1.日期和日期时间类型
2.从字符串生成日期数据
3.日期显示格式
4.访问日期时间的组成值
5.日期舍入计算
6.日期计算
6.1 时间长度
6.2 时间周期
6.3 时间区间
7.基本 R 软件的日期功能
7.1 生成日期和日期时间型数据
7.2 取出日期时间的组成值
7.3 日期计算
练习
1.日期和日期时间类型
R 中日期可以保存为 Date 类型,一般用整数保存,数值为从 1970-1-1 经过的天 数。 R 中用一种叫做 POSIXct 和 POSIXlt 的特殊数据类型保存日期和时间,可以仅包含日期部分,也可以同时有日期和时间。技术上,POSIXct 把日期时间保存为从 1970 年 1 月 1 日零时到该日期时间的时间间隔秒数,所以数据框中需要保存日期时用 POSIXct 比较合适,需要显示时再转换成字符串形式;POSIXlt 把日期时间保存为一个包含年、月、日、星期、时、分、秒等成分的列表,所以求这些成分可以从 POSIXlt 格式日期的列表变量中获得。日期时间会涉及到所在时区、夏时制等问题,比较复杂。 基础的 R 用 as.Date()、as.POSIXct() 等函数生成日期型和日期时间型,R 扩展包 lubridate 提供了多个方便函数,可以更容易地生成、转换、管理日期型和日期时间型数据。载入扩展包的方式:
library(lubridate)
如果下面内容:
![]()
证明你没有安装此扩展包
此时需要安装扩展包,安装方式如下:
点击【程序包】,再点击【安装程序包】
然后,找到 China(Beijing 2)

然后找到需要安装的扩展包 lubridate

然后,点击【确定】即可,安装完成会出现如下内容

这次我们再此载入扩展包 lubridate

2.从字符串生成日期数据
函数 lubridate::today() 返回当前日期:
today()
返回:
![]()
函数 lubridate::now() 返回当前日期时间:
now()
返回:
![]()
在结果中,我们看到了 CST 字样,CST 是时区,这里使用了操作系统提供的当前时区。CST 不是一个含义清晰的时区,在不同国家对应不同的时区,在中国代表中国标准时间(北京时间)
用 lubridate::ymd(), lubridate::mdy(), lubridate::dmy() 将字符型向量转换为日期型向量,但是他们的输入方式不相同,y 表示年,m 表示月,d 表示日,如: 年 - 月 - 日:ymd(c("2022-1-24","2022-01-24"))
返回:
![]()
月 - 日 - 年:
mdy(c("1-24-2022", "01-24-2022"))
返回:
![]()
日 - 月 - 年:
dmy(c("24-1-2022","24-01-2022"))
返回:
![]()
如果在年号只有两位数字时,默认对应到 1969-2068 范围。
lubridate::make_date(year, month, day) 可以从三个数值构成日期向量。如make_date(2022, 1, 24)
返回:
![]()
ymd_hms("2022-1-24 19:26:35") 返回:
![]()
make_datetime(2022, 1, 24, 19, 32, 36) 返回:
![]()
用 lubridate::as_date() 可以将日期时间型转换为日期型,如
as_date(as.POSIXct("2022-01-24 19:32:36"))
返回:
![]()
用 lubridate::as_datetime() 可以将日期型数据转换为日期时间型,如
as_datetime(as.Date("2022-01-24"))
返回:
![]()
3.日期显示格式
用 as.character() 函数把日期型数据转换为字符型, 如x <- as.POSIXct(c('2022-1-24', '2022-01-24'))
as.character(x)
返回:
![]()
在 as.character() 中可以用 format 选项指定显示格式,格式中 “%Y” 代表四位的公元年号,“%m” 代表两位的月份数字,“%d” 代表两位的月内日期号
如 %m/%d/%Y 表示 月-日-年
x <- as.POSIXct(c('2022-1-24', '2022-01-24'))
as.character(x, format='%m/%d/%Y')
返回:
![]()
x <- as.POSIXct(c('2022-1-24', '2022-01-24'))
old.lctime <- Sys.getlocale('LC_TIME')
Sys.setlocale('LC_TIME', 'C') 返回:
![]()
as.character(x, format='%b%y') 返回:
![]()
Sys.setlocale('LC_TIME', old.lctime) 返回:
![]()
包含时间的转换,如
x <- as.POSIXct('2022-1-24 19:56:42')
as.character(x) 返回:
![]()
as.character(x, format='%H:%M:%S') 返回:
![]()
4.访问日期时间的组成值
lubridate 包的如下函数可以取出日期型或日期时间型数据中的组成部分:- • year() 取出年
- • month() 取出月份数值
- • mday() 取出日数值
- • yday() 取出日期在一年中的序号,元旦为 1
- • wday() 取出日期在一个星期内的序号,但是一个星期从星期天开始,星期天为 1, 星期一为 2,星期六为 7。
- • hour() 取出小时
- • minute() 取出分钟
- • second() 取出秒
month(as.POSIXct("2022-1-24 19:56:42")) 返回:
![]()
提取日
mday(as.POSIXct("2022-1-24 19:56:42")) 返回:
![]()
提取日期在一个星期内的序号
wday(as.POSIXct("2022-1-24 19:56:42")) lubridate 的这些成分函数还允许被赋值,结果就修改了相应元素的值,如 将年份由 2022 赋值为 2000 x <- as.POSIXct("2022-1-24 20:08:15")
year(x) <- 2000
month(x) <- 1
mday(x) <- 1
x 返回:
![]()
update() 可以对一个日期或一个日期型向量统一修改其组成部分的值,如
x <- as.POSIXct("2022-1-24 20:08:15")
y <- update(x, year=2000)
y
返回:
![]()
5.日期舍入计算
lubridate 包提供了 floor_date(), round_date(), ceiling_date() 等函数,对日期可以用 unit= 指定一个时间单位进行舍入。时间单位为字符串,如 seconds, 5 seconds, minutes, 2 minutes, hours, days, weeks, months, years 等。 比如,以 10 minutes 为单位,floor_date() 将时间向前归一化到 10 分钟的整数倍:x <- ymd_hms("2022-1-24 20:08:15")
floor_date(x, unit="10 minutes")
返回:
![]()
ceiling_date() 将时间向后归一化到 10 分钟的整数倍:
x <- ymd_hms("2022-1-24 20:08:15")
ceiling_date(x, unit="10 minutes")
返回:
![]()
round_date() 将时间归一化到最近的 10 分钟的整数倍,时间恰好是 5 分钟倍数时按照类似四舍五入的原则向上取整。例如
x <- ymd_hms("2022-1-24 20:08:15")
round_date(x, unit="10 minutes")
返回:
![]()
如果单位是星期,会涉及到一个星期周期的开始是星期日还是星期一的问题。用参数week_start=7 指定开始是星期日,week_start=1 指定开始是星期一。
6.日期计算
在 lubridate 的支持下日期可以相减,可以进行加法、除法。lubridate 包提供了如下的三种与时间长短有关的数据类型:- • 时间长度 (duration),按整秒计算
- • 时间周期 (period),如日、周
- • 时间区间 (interval),包括一个开始时间和一个结束时间
6.1 时间长度
R 的 POSIXct 日期时间之间可以相减,如d1 <- ymd_hms("2022-01-24 0:0:0")
d2 <- ymd_hms("2022-01-24 12:0:5")
di <- d2 - d1; di 返回:
![]()
结果显示与日期之间差别大小有关系,结果是类型是 difftime。
lubridate 包提供了 duration 类型,处理更方便:
as.duration(di)
返回:
![]()
dhours(1) 返回:
![]()
dhours(1) + dseconds(5) 返回:
![]()
dhours(1)*10 返回:
![]()
可以给一个日期加或者减去一个时间长度,结果严格数按推移的秒计算,如
d2 <- ymd_hms("2022-01-24 12:0:5")
d2 - dhours(5)
返回:
![]()
d2 <- ymd_hms("2022-01-24 12:0:5")
d2 + ddays(10)
返回:
![]()
时间的前后推移在涉及到时区和夏时制时有可能出现未预料到的情况。
用 unclass() 函数将时间长度数据的类型转换为普通数值,如:
unclass(dhours(1))
返回:
![]()
6.2 时间周期
时间长度的固定单位是秒,但是像月、年这样的单位,因为可能有不同的天数,所以日历中的时间单位往往没有固定的时长。 lubridate 包的 seconds(), minutes(), hours(), days(),weeks(), years() 函数可以生成以日历中正常的周期为单位的时间长度,不需要与秒数相联系,可以用于时间的前后推移。这些时间周期的结果可以相加、乘以无量纲整数:years(2) + 10*days(1) 返回:
![]()
lubridate 的月度周期因为与已有函数名冲突,所以没有提供,需要使用 lubridate::period(num, units="month") 的格式,其中 num 是几个月的数值。
为了按照日历进行日期的前后平移,而不是按照秒数进行日期的前后平移,应该使用这些时间周期。例如,因为 2016 年是闰年,按秒数给 2016-01-01 加一年,得到的并不是 2017-01-01:ymd("2016-01-01") + dyears(1)
返回:
![]()
使用时间周期函数则得到预期结果:
ymd("2016-01-01") + years(1)
返回:
![]()
6.3 时间区间
lubridate 提供了%--% 运算符构造一个时间期间。时间区间可以求交集、并集等。构造如:
d1 <- ymd_hms("2000-01-01 0:0:0")
d2 <- ymd_hms("2000-01-02 12:0:5")
din <- (d1 %--% d2); din
返回:
![]()
对一个时间区间可以用除法计算其时间长度,如
din / ddays(1)
返回:
![]()
din / dseconds(1)
返回:
![]()
生成时间区间,也可以用 lubridate::interval(start, end) 函数,如
interval(ymd_hms("2000-01-01 0:0:0"), ymd_hms("2000-01-02 12:0:5"))
返回:
![]()
可以指定时间长度和开始日期生成时间区间,如
d1 <- ymd("2022-01-24")
din <- as.interval(dweeks(1), start=d1); din
返回:
![]()
int_start(din)
返回:
![]()
int_end(din)
返回:
![]()
din2 <- int_shift(din, by=ddays(3)); din2 返回:
![]()
用 lubridate::int_overlaps() 判断两个时间区间是否有共同部分,如
int_overlaps(din, din2)
返回:
![]()
int_intersect <- function(int1, int2){
n <- length(int1)
int1 <- lubridate::int_standardize(int1)
int2 <- lubridate::int_standardize(int2)
sele <- lubridate::int_overlaps(int1, int2)
inter <- rep(lubridate::interval(NA, NA), n)
if(any(sele)){
inter[sele] <-
lubridate::interval(pmax(lubridate::int_start(int1[sele]),
lubridate::int_start(int2[sele])),
pmin(lubridate::int_end(int1[sele]),
lubridate::int_end(int2[sele])))
}
inter
} 测试如下:
d1 <- ymd(c("2018-01-15", "2018-01-18", "2018-01-25"))
d2 <- ymd(c("2018-01-21", "2018-01-23", "2018-01-30"))
din <- interval(d1, d2); din 返回:

接下来,我们用用上面自定义的函数试试:
首先得先导入这个函数
source("D:/桌面/R语言/int_intersect.r") 然后,我们调用一下
int_intersect(rep(din[1], 2), din[2:3]) 返回:
![]()
此自定义函数还可以进一步改成允许两个自变量长度不等的情形。
7.基本 R 软件的日期功能
7.1 生成日期和日期时间型数据
对 yyyy-mm-dd 或 yyyy/mm/dd 格式的数据,可以直接用 as.Date() 转换为 Date 类型,如:x <- as.Date("2022-1-24"); x
返回:
![]()
as.numeric(x)
返回:
![]()
as.Date() 可以将多个日期字符串转换成 Date 类型,如
as.Date(c("2022-1-24", "2022-01-24"))
返回:
![]()
as.Date("1/24/2022", format="%m/%d/%Y") 返回:
![]()
as.POSIXct(c('2022-1-24'))
返回:
![]()
as.POSIXct(c('2022/01/24'))
返回:
![]()
as.POSIXct('2022-01-24 13:15:45') 返回:
![]()
as.POSIXct(c('1998-03-16 13:15:45', '2015-11-22 9:45:3'))
返回:
![]()
x <- as.POSIXct(c('1998-03-16 13:15:45', '2015-11-22 9:45:3'))
attributes(x) 返回:

在 as.POSIXct() 函数中用 format 参数指定一个日期格式。如
as.POSIXct('1/24/22', format='%m/%d/%y')
返回:
![]()
as.POSIXct(paste('1991-12', '-01', sep=''), format='%Y-%m-%d') 返回:
![]()
又如
old.lctime <- Sys.getlocale('LC_TIME')
Sys.setlocale('LC_TIME', 'C') 返回:
![]()
as.POSIXct(paste('01', 'DEC91', sep=''), format='%d%b%y') 返回:
![]()
Sys.setlocale('LC_TIME', old.lctime) 返回:
![]()
把'DEC91' 转换成了’1991-12-01’。
如果明确地知道时区,在 as.POSIXct() 和 as.POSIXlt() 中可以加选项 tz= 字符串。选项 tz 的缺省值为空字符串,这一般对应于当前操作系统的默认时区。但是,有些操作系统和 R 版本不能使用默认值,这时可以为 tz 指定时区,比如北京时间可指定为 tz='Etc/GMT+8'。如as.POSIXct('1949-10-01', tz='Etc/GMT+8')
返回:
![]()
7.2 取出日期时间的组成值
把一个 R 日期时间值用 as.POSIXlt() 转换为 POSIXlt 类型,就可以用列表元素方法取出其组成的年、月、日、时、分、秒等数值。如x <- as.POSIXct('1998-03-16 13:15:45')
y <- as.POSIXlt(x)
cat(1900+y$year, y$mon+1, y$mday, y$hour, y$min, y$sec, '\n') 返回:
![]()
x <- as.POSIXct(c('1998-03-16', '2015-11-22'))
as.POSIXlt(x)$year + 1900 返回:
![]()
7.3 日期计算
因为 Date 类型是用数值保存的,所以可以给日期加减一个整数,如:x <- as.Date("1970-1-5")
x1 <- x + 10; x1
返回:
![]()
x2 <- x - 5; x2
返回:
![]()
as.POSIXct(c('1998-03-16 13:15:45')) - 30 返回:
![]()
as.POSIXct(c('1998-03-16 13:15:45')) + 10 返回:
![]()
as.POSIXct(c('1998-03-16 13:15:45')) + 3600*24*2 返回:
![]()
x <- as.POSIXct(c('1998-03-16', '2015-11-22'))
c(difftime(x[2], x[1], units='days'))
返回:
![]()
x <- as.POSIXct(c('1998-03-16 13:15:45', '2015-11-22 9:45:3'))
c(difftime(x[2], x[1], units='days'))
返回:
![]()
difftime() 中 units 选项还可以取为 'secs', 'mins', 'hours' 等。
练习
设文件dates.csv中包含如下内容: "出生日期","发病日期" "1941/3/8","2007/1/1" "1972/1/24","2007/1/1" "1932/6/1","2007/1/1" "1947/5/17","2007/1/1" "1943/3/10","2007/1/1" "1940/1/8","2007/1/1" "1947/8/5","2007/1/1" "2005/4/14","2007/1/1" "1961/6/23","2007/1/2" "1949/1/10","2007/1/2" 把这个文件读入为 R 数据框 dates.tab,运行如下程序定义 date1 和 date2 变量:date1 <- dates.tab[,' 出生日期']
date2 <- dates.tab[,' 发病日期']
(1) 把 date1、date2 转换为 R 的 POSIXct 日期型。
(2) 求 date1 中的各个出生年。
(3) 计算发病时的年龄,以周岁论(过生日才算)
(4) 把 date2 中发病年月转换为’monyy’ 格式,这里 mon 是如 FEB 这样英文三字母缩写,yy 是两数字的年份。 (5) 对诸如’FEB91’, ’OCT15’ 这样的年月数据,假设 00—20 表示 21 世纪年份,21—99 表示 20 实际年份。编写 R 函数,输入这样的字符型向量,返回相应的 POSIXct 格式日期,具体日期都取为相应月份的 1 号。这个习题和后两个习题可以预习函数部分来做。 (6) 对 R 的 POSIXct 日期,写函数转换成’FEB91’, ’OCT15’ 这样的年月表示,假设 00—20 表示 21 世纪年份,21—99 表示 20 实际年份。 (7) 给定两个 POSIXct 日期向量 birth 和 work,birth 为生日,work 是入职日期,编写 R 函数,返回相应的入职周岁整数值(不到生日时周岁值要减一)。
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
