日期时间是一类独特的数据,在实际中有众多的应用。R语言的基础包中提供了两种类型的时间数据,一类是Date日期数据,它不包括时间和时区信息,另一类是POSIXct/POSIXlt类型数据,其中包括了日期、时间和时区信息。
使用使用ISOdate(),创建ISO 8601标准的日期和时间,如上图。
ISOdate(year = 2019,month = 12, day = 12, hour = 8, min = 5, sec = 3, tz = "UTC") [1] "2019-12-12 08:05:03 UTC"
POSIX表示 Portable Operating System Interface。POSIXct表示自1970年(UTC)开始的秒数,ct表示日历时间。
release_date <- as.POSIXct("2021-12-12 08:05:03") class(release_date) unclass(release_date)
POSIXlt表示列表中的以下信息。
POSIXlt的lt表示local time。使用unclass或者unlist提取POSIXlt的时间和日期组件。
release_date <- as.POSIXlt("2021-12-12 08:05:03") release_date release_date <- as.POSIXlt("2021-12-12 08:05:03") unclass(release_date) unlist(release_date) release_date$hour release_date$mon release_date$zone
日期data,存储的是天;时间POSIXct 存储的是秒,POSIXlt 打散,年月日不同;日期-时间=不可运算。一般来讲,R语言中建立时序数据是通过字符型转化而来,但由于时序数据形式多样,而且R中存贮格式也是五花八门,例如Date/ts/xts/zoo/tis/fts等等。lubridate包,timeDate包,都有用。如果输入的格式不是标准格式,则同样需要使用strptime函数,利用format来进行指定。
在R中自带的日期形式为:as.Date(),以数值形式存储。对于规则的格式,则不需要用format指定格式;如果输入的格式不规则,可以通过format指定的格式读入;其中以1970-01-01定义为第0天,之后的年份会以距离这天来计算。我们先获知下当前日期和时间。
Sys.Date() #返回当前日期。 Sys.time() #返回日期、时间和时区。
格式 | %d | %m | %Y | %y |
---|---|---|---|---|
意义 | 月份中某天 | 月份,以数字形式表示 | 年份,以四位数字表示 | 年份,以两位数字表示 |
格式 | %H | %M | %S |
---|---|---|---|
意义 | 24小时制小时 | 十进制分钟 | 十进制秒 |
weekdays()取日期对象所处的周几;months()取日期对象的月份;quarters()取日期对象的季度。
POSIXct 是以1970年1月1号开始的以秒进行存储,如果是负数,则是1970-01-01年以前;正数则是1970年以后。POSIXlt是以列表的形式存储:年、月、日、时、分、秒,作用是打散时间;
主要特点:作用是打散时间,把时间分成年、月、日、时、分、秒,并进行存储,可以作为时间筛选的一种。
主要特点:以秒进行存储。
Sys.Date() #字符串类型
typeof(Sys.Date()) #系统日期类型
相同的格式才能相互减,不能加。二进列的+法对"Date"、"POSIXt"对象不适用。
as.Date("2011-07-01") - as.Date(today()) as.POSIXct(today()-as.POSIXct(as.Date("2012-10-25 01:00:00")) as.POSIXlt(today())-as.POSIXlt(as.Date("2012-10-25 01:00:00"))
相互减之后,一般结果输出的天数。
不同格式的时间都可以进行运算。并且可以实现的是计算两个时间间隔:秒、分钟、小时、天、星期。但是不能计算年、月、季度的时间差。
gtd <- as.Date("2011-07-01") difftime(as.POSIXct(today(), gtd, units="hours") #只能计算日期差,还可以是“secs”, “mins”, “hours”, “days”
该函数是将字符型时间转化为 "POSIXlt" 和"POSIXct"两类。跟format比较相似。strptime之后的时间是可以直接做减法,因为直接是"POSIXlt" 和"POSIXct"格式了。
strptime("2006-01-08 10:07:52", "%Y-%m-%d")-strptime("2006-01-15 10:07:52", "%Y-%m-%d") class(strptime("2006-01-08 10:07:52", "%Y-%m-%d"))
加载入扩展包lubridate
library(lubridate)
用 lubridate::ymd(), lubridate::mdy(), lubridate::dmy() 将字符型向量转换为日期型向量,但是他们的输入方式不相同,y 表示年,m 表示月,d 表示日,如:年-月-日:
ymd(c("2022-1-24","2022-01-24")) #规范化格式化日期数据 ymd_hms("2022-1-24 19:26:35") make_datetime(2022, 1, 24, 19, 32, 36)
lubridate 包的 ymd、mdy、dmy 等函数添加 hms、hm、h 等后缀,可以用于将字符串转换成日期时间。
lubridate::make_datetime(year, month, day, hour, min, sec) 可以从最多六个数值组成日期时间,其中时分秒缺省值都是 0。
lubridate::as_date() 可以将日期时间型转换为日期型,如
as_date(as.POSIXct("2022-01-24 19:32:36")) [1] "2022-01-24"
lubridate 包的如下函数可以取出日期型或日期时间型数据中的组成部分:
year(as.POSIXct("2022-1-24 19:56:42")) [1] 2022 month(as.POSIXct("2022-1-24 19:56:42")) [1] 1 yday(as.POSIXct("2022-1-24 19:56:42")) [1] 24 hour(as.POSIXct("2022-1-24 19:56:42")) [1] 19 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')
update() 可以对一个日期或一个日期型向量统一修改其组成部分的值。update() 函数中可以用 year, month, mday, hour, minute, second 等参数修改日期的组成部分。
x <- as.POSIXct("2022-1-24 20:08:15") y <- update(x, year=2000)
用 as.POSIXct() 函数把年月日格式的日期转换为R的标准日期,没有时间部分就认为时间在午夜,也可以将秒值转化为规范化的日期时间格式,在许多数据文件转入日期数据时会变成数值,然后通过R的日期时间函数转化为日期,当然有时也要拆分日期中的成分,这些操作给处理带来了极大的便利。年月日中间的分隔符可以用减号也可以用正斜杠,但不能同时有减号又有斜杠。
as.POSIXct(c('2022-1-24')) [1] "2022-01-24 CST" as.POSIXct(5557776231,origin="1970-01-01") [1] "2146-02-13 10:43:51 CST"
x<-as.POSIXct(5557776231,origin="1970-01-01") hour(x) year(x) month(x) mday(x)
可随心所欲根据需要转化成日期数据,在实际处理中效率很高。
paste0(year(x),"-",month(x),"-",mday(x)) [1] "2146-2-13"
rm(list = ls()) library(stringr) library(tidyverse) library(lubridate) df=read.table("clipboard",header=T) tt<-as.POSIXlt(df[,1],origin ='1970-01-01') tt1=paste0(year(tt),"-",month(tt),"-",mday(tt)) tt2<- ymd(tt1) tt3 <- data.frame(tt1,hour(tt))
tt1 [1] "2017-11-29" "2017-11-29" "2017-11-30" "2017-11-30" "2017-12-1" "2017-12-1" [7] "2017-12-1" "2017-12-1" "2017-12-1" "2017-12-1" "2017-12-1" "2017-12-1" [13] "2017-12-1" "2017-12-1" "2017-12-1" "2017-12-1" "2017-12-1" "2017-12-1" [19] "2017-12-1" "2017-12-1" "2017-12-1" "2017-12-1" "2017-12-1" "2017-12-1" [25] "2017-12-1" "2017-12-1" "2017-12-1" "2017-12-1" "2017-12-1" tt3 tt1 hour.tt. 1 2017-11-29 23 2 2017-11-29 23 3 2017-11-30 17 4 2017-11-30 23 5 2017-12-1 6 6 2017-12-1 14
日期数据用的相对少,但又非常专业,需要细心整理与修炼。设文件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 函数,返回相应的入职周岁整数值(不到生日时周岁值要减一)。
1.(R语言与格式,日期格式,格式转化的操作)[http://www.zzvips.com/article/218802.html]
2.(R语言编程③——数据结构(字符串、日期时间))[https://zhuanlan.zhihu.com/p/436971997]
3.(R语言学习:日期和时间相关知识)[https://zhuanlan.zhihu.com/p/463571494]