日期时间数据的处理—R语言

2023-06-13,,

日期时间是一类独特的数据,在实际中有众多的应用。R语言的基础包中提供了两种类型的时间数据,一类是Date日期数据,它不包括时间和时区信息,另一类是POSIXct/POSIXlt类型数据,其中包括了日期、时间和时区信息。

一、ISO 8601标准的日期和时间

使用使用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"

1.1 POSIX

POSIX表示 Portable Operating System Interface。POSIXct表示自1970年(UTC)开始的秒数,ct表示日历时间。如果是负数,则是1970-01-01年以前;正数则是1970年以后。POSIXlt是以列表的形式存储:年、月、日、时、分、秒,作用是打散时间。

release_date <- as.POSIXct("2021-12-12 08:05:03")
class(release_date)
unclass(release_date)

1.2 POSIXlt

POSIXlt表示列表中的以下信息。

seconds minutes hour
day of the month
month
year
day of week
day of year
daylight saving time flag
time zone
offset in seconds from GMT

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

1.3 小结

当没有时间组件时使用Date
在处理时间和时区时使用POSIX
当您想要访问/提取不同的组件时,请使用POSIXlt

日期data,存储的是天;时间POSIXct 存储的是秒,POSIXlt 打散,年月日不同;日期-时间=不可运算。一般来讲,R语言中建立时序数据是通过字符型转化而来,但由于时序数据形式多样,而且R中存贮格式也是五花八门,例如Date/ts/xts/zoo/tis/fts等等。lubridate包,timeDate包,都有用。如果输入的格式不是标准格式,则同样需要使用strptime函数,利用format来进行指定。

二、日期型和时间型数据

2.1 as.Date函数

在R中自带的日期形式为:as.Date(),以数值形式存储。对于规则的格式,则不需要用format指定格式;如果输入的格式不规则,可以通过format指定的格式读入;其中以1970-01-01定义为第0天,之后的年份会以距离这天来计算。我们先获知下当前日期和时间。

Sys.Date()                #返回当前日期。
Sys.time() #返回日期、时间和时区。

2.2 %d%y%m-基本格式

格式 %d %m %Y %y
意义 月份中某天 月份,以数字形式表示 年份,以四位数字表示 年份,以两位数字表示
示例 00-31 00-12 2007 07
格式 %H %M %S
意义 24小时制小时 十进制分钟 十进制秒
示例 00-24 00-60 00-60

weekdays()取日期对象所处的周几;months()取日期对象的月份;quarters()取日期对象的季度。

三、时间运算

3.1 基本运算函数

Sys.Date() #字符串类型

typeof(Sys.Date()) #系统日期类型

3.2 直接加减

相同的格式才能相互减,不能加。二进列的+法对"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"))

相互减之后,一般结果输出的天数。

3.3 difftime函数――计算时差

不同格式的时间都可以进行运算。并且可以实现的是计算两个时间间隔:秒、分钟、小时、天、星期。但是不能计算年、月、季度的时间差。

gtd <- as.Date("2011-07-01")
difftime(as.POSIXct(today(), gtd, units="hours") #只能计算日期差,还可以是“secs”, “mins”, “hours”, “days”

3.4 strptime函数

该函数是将字符型时间转化为 "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)

4.1 规范化日期和时间

用 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"

4.2 访问日期时间的组件值

lubridate 包的如下函数可以取出日期型或日期时间型数据中的组成部分:

year() 取出年
month() 取出月份数值
mday() 取出日数值
yday() 取出日期在一年中的序号,元旦为 1
wday() 取出日期在一个星期内的序号,但是一个星期从星期天开始,星期天为 1, 星期一为 2,星期六为 7。
hour() 取出小时
minute() 取出分钟
second() 取出秒

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)

4.3 数值转化为日期和时间

用 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"

4.4 字符串转化为日期

as.Date()函数

把字符串转换为日期,系统默认格式yyyy-mm-dd

Date1<-as.Date(c("2020-07-19","2020-07-20"))
Date<-c("06/20/20","06/21/20","06/22/20","06/23/20","06/24/20","06/25/20")
Date2<-as.Date(Date,"%m/%d/%Y")
修改数据框中的日期格式
#构建数据框
PatientID<-c(1,2,3,4,5,6)
Date<-c("06/20/20","06/21/20","06/22/20","06/23/20","06/24/20","06/25/20")
Age<-c(18,25,26,35,48,50)
Gender<-c("M","F","F","M","F","M")
City<-c("福州","厦门","泉州","龙岩","漳州","三明")
Pr1<-c("69","57","67","65","72","55")
S1<-c(88,78,NA,56,45,60)
mydata<-data.frame(PatientID,Date,Age,Gender,City,Pr1,S1)
mydata
PatientID Date Age Gender City Pr1 S1
1 1 06/20/20 18 M 福州 69 88
2 2 06/21/20 25 F 厦门 57 78
3 3 06/22/20 26 F 泉州 67 NA
4 4 06/23/20 35 M 龙岩 65 56
5 5 06/24/20 48 F 漳州 72 45
6 6 06/25/20 50 M 三明 55 60
#修改数据框日期格式
mydata$Date<-as.Date(mydata$Date,"%m/%d/%Y")
mydata
PatientID Date Age Gender City Pr1 S1
1 1 0020-06-20 18 M 福州 69 88
2 2 0020-06-21 25 F 厦门 57 78
3 3 0020-06-22 26 F 泉州 67 NA
4 4 0020-06-23 35 M 龙岩 65 56
5 5 0020-06-24 48 F 漳州 72 45
6 6 0020-06-25 50 M 三明 55 60

4.5 实际应用

剪贴板中数据如下:

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))
tt2
[1] "2017-11-29" "2017-11-29" "2017-11-30" "2017-11-30" "2017-12-01" "2017-12-01"
[7] "2017-12-01" "2017-12-01" "2017-12-01" "2017-12-01" "2017-12-01" "2017-12-01"
[13] "2017-12-01" "2017-12-01" "2017-12-01" "2017-12-01" "2017-12-01" "2017-12-01"
[19] "2017-12-01" "2017-12-01" "2017-12-01" "2017-12-01" "2017-12-01" "2017-12-01"
[25] "2017-12-01" "2017-12-01" "2017-12-01" "2017-12-01"
tt3
tt2 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-01 6
6 2017-12-01 14

总结

日期数据用的相对少,但又非常专业,需要细心整理与修炼。常常在数据的深度分析,特别是利用时间序列绘制循环静态图、日历图、旭日图、螺旋图或者动态GIF/VIDEO等时出现Bug,罪魁祸首往往是因为日期值与字符型变量的相互转换、日期值的算术运算以及函数使用错误导致的。

参考文献

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]

日期时间数据的处理—R语言的相关教程结束。

《日期时间数据的处理—R语言.doc》

下载本文的Word格式文档,以方便收藏与打印。