参考资料:学习R
1、日期和时间类
R中自带有三个日期和时间类:POSIXct、POSIXlt和Date。
(1)POSI日期和时间
POSIX日期和时间是R的经典程序。R中的两个标准日期—时间类是POSIXct和POSIXlt。POSIX是一套标准,它定义了那些需要遵守的Unix的规定,例如日期和时间该如何设定。ct是“日历时间”(calendar time)的简称,POSIXct类记录了以世界标准时(UTC)为准的从1970开始计时的秒数计数。POSIXlt将日期存储为一个列表,其中包括秒、分钟、小时和月份等。POSIXct最适用于存储和计算时间,而POSIXlt最适用于提取日期中的某个特定部分。
函数Sys.time将以POSIXct的形式返回当前的日期和时间:
now_ct<-Sys.time()
print(now_ct)
现在,now_ct类有两个元素:一个是POSIXct变量,还有POSIXct继承自类POSIXt:
当日期被打印出来时,我们只看到它格式化后的版本,因而不确定日期是如何被存储的。通过使用unclass,我们发现它只是一个数字:
打印时,POSIXlt日期看上去几乎都一样。然而,它们的底层存储机制是非常不同的:
now_lt<-as.POSIXlt(now_ct)
print(now_lt)
class(now_lt)
unclass(now_lt)
对于POSIXlt日期来说,可以使用列表索引来单独访问其每个部分:
now_lt$sec
now_lt$min
(2)Date类
在R的基本包中,Date类存储了从1970年开始计算的天数。Date类最适用于当我们不在乎一天中的某个时刻时。
now_date<-as.Date(now_ct)
print(now_date)
class(now_date)
unclass(now_date)
(3)其他日期类
R中还有其他许多处理日期和时间的类。如果需要选择日期—时间类,通常我们应该坚持使用三个基本类(POSIXct、POSIXlt和Date)中的一个。其他来自于各种插件包的日期时间类包括 date、dates、chron、yearmon、yearqtr、timeDate、ti和jul。
2、日期与字符串的相互转换
许多数据的文本文件格式并没有明确支持某种特定的日期类型。例如,在一个 CSV 文件中, 每个值只是一个字符串。为了使用 R 中日期函数,你必须把日期字符串转换成某一个日期类型的变量。类似地,往CSV文件中写数据时,你也必须首先把日期转换成字符串。
(1)解析日期
当我们从文本或电子表格文件读取日期时,它们通常被存储为一个字符向量或因子。为了把它们转换为日期,我们需要解析这些字符串。我们可以使用strptime函数(string parse time的简称),它将返回POSIXlt日期(还有as.POSIXct函数和as.POSIXlt函数,调用它们时,如果输入的是字符,那么它们只是strptime的封装函数)。解析日期时,我们必须把字符串与其日期对应的那些位告诉strptime。日期的格式使用带有百分号和字符的字符串来指定。例如,当月的第几天被指定为%d。把它们与其他固定字符相结合可以形成一个完整的规范。例如:冒号、破折号和日期中的斜杠。
在下例中,%H是小时(24小时制),%M是分钟,%S是秒,%m是月数,%d是当月的第几天,%Y为四位数的年数。
moon_landings_str<-c(
"20:17:40 20/07/1969",
"06:54:35 17/11/1969",
"09:18:11 05/02/1971",
"22:16:29 30/07/1971",
"02:23:35 21/04/1972",
"19:54:57 11/12/1972"
)
moon_landings_lt<-strptime(
moon_landings_str,
"%H:%M:%S %d/%m/%Y",
tz="UTC"
)
print(moon_landings_lt)
如果字符串不匹配格式字符串的格式,那么它就取NA值。例如如果给出的是破折号而不是斜线,将使得解析失败:
(2)格式化日期
与解析相反的问题是如何把日期变量转换为字符串,即格式化。在这种情况下,我们将使用与指定格式字符串相同的系统,不过现在调用 strftime(字符串格式的时间)来反转解析操作。如果觉得strftime不好记,我们可以使用format函数来轻松完成日期的格式化,与strftime函数的使用方法几乎是一样的。
下例中,%I表示小时(12小时制),%p是AM/PM指示,%A是星期几的全称,而%B是月的全名。strftime可使用POSIXct和POSIXlt的输入参数:
now_ct<-Sys.time()
strftime(now_ct," It's %I:%M:%p on %A %d %B, %Y.")
3、时区
从编程的角度来看,时区往往比较复杂。很多国家常有好几个时区, 而且当一些(但不是全部) 国家切换到夏令时需要改变边界。 许多时区都有缩写名称, 但它们又不是唯一的。
在解析日期字符串是(使用strptime),我们可以指定一个时区;当我们格式化它是(使用strftime),可以再次改变它。在解析过程中如果不指定时区(默认为"")。R会给日期以默认时区。这个值是Sys.timezone返回的,它会从我们的操作系统区域设置猜到该值。我们可以使用Sys.getlocale("LC_TIME")来查看操作系统的日期时间设定。
要避免这种时区的混乱,最简单的方法是随机记录,然后以UTC时区分析我们的时间。
strftime(now_ct,tz="America/Los_Angeles")
strftime(now_ct,tz="Africa/Brazzaville")
strftime(now_ct,tz="Australia/adelaide")
使用file.path(R.home("share"),"zoneinfo","zone.tab")能查找出R中所有可能的Olson时区列表。
另一个可靠的方法是给UTC手动添加一个偏移量,格式为 "UTC"+n" 或 "UTC"-n"。 负的时间在UTC的东边,正的在西边。
strftime(now_ct,tz="UTC-5")
strftime(now_ct,tz="-5")
指定时区的第三个方法是使用缩写,可以是三个字母或三个字母加一个数字再加三个字母的方式。这种方法不到最后不要使用,原因有三个:首先,缩写难以阅读,更容易出错;其次,正如前面提到的,它们不是唯一的,所以给出的时区可能不是你所要的;最后,不同的操作系统支持不同的缩写集。尤其对于 Windows 操作系统来说,它对时区缩写的处理比较别扭。
最后的关于时区的警告是:strftime将忽略POSIXlt类型的时区变更。最好在打印之前就显式把日期转换成 POSIXct 类型:
还有一个最后警告:如果我们调用带有 POSIXlt 参数的连接函数c,它会把时区更改为当地时区。相反,如果把 c 函数作用于POSIXct 参数上,将彻底去除其时区属性。(大多数其他的函数都将假定日期是本地时区的,但要小心!)