R语言日期处理的一些问题
使用R语言的很多都知道,其对于日期处理有时候会很麻烦,这里总结一些列子,希望有所帮助
注:这里主要描述日期识别,其他的计算参考下文中的R包,此处不细述
基础日期函数
as.Date("2012-12-14")
#[1] "2012-12-14"
as.Date("2012/12/14")
[1] "2012-12-14"
as.Date("2012\12\14")
# Error in charToDate(x) : 字符串的格式不够标准明确
as.Date("2012.12.14")
# Error in charToDate(x) : 字符串的格式不够标准明确
这里可以看出通常的日期格式as.Date自动识别有限,有人可能说它有个参数,可以指定识别方式,但如果大批量数据进入,想自动统一识别还是有点难的,下面可以试试:lubridate::as_datetime
例如:
lubridate::as_datetime("2012.04/1612:00:05")
#[1] "2012-04-16 12:00:05 UTC"
这个包对日期的处理还是比较方便的,到此绝大部分大批量日期数据格式都已经识别完成,此时,可能有一个问题产生了,Execl导入数据中明明显示日期,R中却是数字
那么,这个问题是怎么产生的呢?其实,这是execl存储机制的问题,execl中日期存储除非你设定单元格格式为文本,不然你正常输入日期,其自动默认为日期格式,此时,其内部核心存储实际为这个日期距离1900-01-00 00:00:00
的天数,我们可以在execl中输入0,调整其单元格格式,自定义选择yyyy/m/d h:mm
就可以发现这个问题
如何解决呢?
办法一
1.在execl中利用函数`TEXT(位置,"yyyy-mm-dd HH:MM:SS")`转成文本格式,方便数据读取,但小批量还好,大批量也是很麻烦,还不说execl能不能反应过来
办法二
### 这里借助as.Date函数,需要注意的是需要类型转换,基线往后推两天,
### 但这里也有个小缺陷,就是只能识别到天,
### 时分秒丢失,对于有些严格的数据来说,比如医学死亡时间,具体到时分秒此时,就不可取了
1. as.Date(as.numeric("44677.4375"),origin = "1899-12-30")
### 利用lubridate包
2. lubridate::as_datetime(44677.4375*24*60*60, origin = as.POSIXct("1899-12-30 00:00:00",tz = "UTC"))
#[1] "2022-04-26 10:30:00 UTC"
注意: 使用lubridate
时,其要求的这种数字转换涉及POSIXct
格式,什么意思呢,POSIXct
实际是以秒为单位存储日期的一种格式,所以明白了
,我们execl中的日期需要转换成秒为单位,才可以,tz必须注明
,不然时区对不上;此外:这里的转换是数字计算,如果不呢,不用慌,R语言字符串转表达式
即可解决:parse
与eval
连用
a <- paste("44677.4375","*24*60*60",sep = "")
#[1] "44677.4375*24*60*60"
### 这里注意参数text无法省略,必须指明
parse(text = a)
#expression(44677.4375*24*60*60)
eval(parse(text = a))
#[1] 3860130600
### 验证下
lubridate::as_datetime(3860130600, origin = as.POSIXct("1899-12-30 00:00:00",tz = "UTC"))
#[1] "2022-04-26 10:30:00 UTC"
### 联用
lubridate::as_datetime(eval(parse(text = paste("44677.4375","*24*60*60",sep = ""))),origin = as.POSIXct("1899-12-30 00:00:00",tz = "UTC"))
#[1] "2022-04-26 10:30:00 UTC"
到此结束!感谢大家!
小提示:
其他日期R包:simtimer
install.packages("simtimer")
origin_date <- as.POSIXct("2016-01-01 00:00:00", tz = "UTC")
my_datetime <- as.POSIXct("2016-01-02 01:01:01", tz = "UTC")
my_simdatetime <- as.sim_datetime(my_datetime, origin_date)
my_simdatetime
#> [1] 90061
as.datetime(my_simdatetime, origin_date)
#> [1] "2016-01-02 01:01:01 UTC"
这里simtimer
包依据官方给出的示例,基本lubridate
也都可以解决,有感兴趣的可以了解一下simtimer