R 中的日期-时间和因子一样,是一种特殊的变量。
Sys.Date()
Sys.time()
format(date, format = ...)
#> [1] "2023-11-14"
#> [1] "Date"
#> [1] "November 14 2023"
#> [1] "November 14 2023 Tuesday"
#> [1] "November"
#> [1] "2023/November/Tue 11:25:49"
strptime(chr_datetime, format = ...)
readr::parse_*(chr_datetime, format = ...)
#> [1] "2006-02-20 CST"
#> [1] "POSIXlt" "POSIXt"
#> [1] "2006-02-20"
#> [1] "Date"
表示日期或时间的数据有 3 种类型:
- 日期:在 tibble 中显示为<date>
- 时间:一天中的某个时刻,在 tibble
中显示为<time>
- 日期时间:可以唯一标识某个时刻(通常精确到秒)的日期加时间,在 tibble
中显示为<dttm>
要想得到当前日期或当前日期时间,你可以使用 today()
或
now()
函数:
#> [1] "2023-11-14"
#> [1] "2023-11-14 11:30:17 CST"
ymd()
系列函数是从字符串创建单个日期时间对象的最简方法,也可以接受不带引号的数值。它不需要指定参数,便能自动处理标点和月份、星期的英文全称、缩写。
x = c(20090101, "2009-01-02", "2009 01 03", "2009-1-4", "2009-1,5", "Created on 2009 1 6", "200901 !!! 07")
ymd(x)
#> [1] "2009-01-01" "2009-01-02" "2009-01-03" "2009-01-04" "2009-01-05"
#> [6] "2009-01-06" "2009-01-07"
#> [1] "character"
#> [1] "2017-01-31"
#> [1] "2017-01-31"
#> [1] "2017-01-31"
#> [1] "2017-01-31 20:11:59 UTC"
#> [1] "2017-01-31 08:01:00 UTC"
#> [1] "2017-01-31 UTC"
使用 make_date()
函数创建日期,使用
make_datetime()
函数创建日期时间
flights %>%
select(year, month, day, hour, minute) %>%
mutate(
departure = make_datetime(year, month, day, hour, minute)
)
#> # A tibble: 336,776 × 6
#> year month day hour minute departure
#> <int> <int> <int> <dbl> <dbl> <dttm>
#> 1 2013 1 1 5 15 2013-01-01 05:15:00
#> 2 2013 1 1 5 29 2013-01-01 05:29:00
#> 3 2013 1 1 5 40 2013-01-01 05:40:00
#> 4 2013 1 1 5 45 2013-01-01 05:45:00
#> 5 2013 1 1 6 0 2013-01-01 06:00:00
#> 6 2013 1 1 5 58 2013-01-01 05:58:00
#> 7 2013 1 1 6 0 2013-01-01 06:00:00
#> 8 2013 1 1 6 0 2013-01-01 06:00:00
#> 9 2013 1 1 6 0 2013-01-01 06:00:00
#> 10 2013 1 1 6 0 2013-01-01 06:00:00
#> # ℹ 336,766 more rows
## flights 数据集中的某些时间是将小时和分钟数简单地排列在一起的,需要将其分离
# 自定义分离函数
make_datetime_100 <- function(year, month, day, time) {
make_datetime(year, month, day, time %/% 100, time %% 100)
}
# 应用分离函数
flights_dt <- flights %>%
filter(!is.na(dep_time), !is.na(arr_time)) %>%
mutate(
dep_time = make_datetime_100(year, month, day, dep_time),
arr_time = make_datetime_100(year, month, day, arr_time),
sched_dep_time = make_datetime_100(year, month, day, sched_dep_time),
sched_arr_time = make_datetime_100(year, month, day, sched_arr_time)) %>%
select(origin, dest, ends_with("delay"), ends_with("time"))
flights_dt
#> # A tibble: 328,063 × 9
#> origin dest dep_delay arr_delay dep_time sched_dep_time
#> <chr> <chr> <dbl> <dbl> <dttm> <dttm>
#> 1 EWR IAH 2 11 2013-01-01 05:17:00 2013-01-01 05:15:00
#> 2 LGA IAH 4 20 2013-01-01 05:33:00 2013-01-01 05:29:00
#> 3 JFK MIA 2 33 2013-01-01 05:42:00 2013-01-01 05:40:00
#> 4 JFK BQN -1 -18 2013-01-01 05:44:00 2013-01-01 05:45:00
#> 5 LGA ATL -6 -25 2013-01-01 05:54:00 2013-01-01 06:00:00
#> 6 EWR ORD -4 12 2013-01-01 05:54:00 2013-01-01 05:58:00
#> 7 EWR FLL -5 19 2013-01-01 05:55:00 2013-01-01 06:00:00
#> 8 LGA IAD -3 -14 2013-01-01 05:57:00 2013-01-01 06:00:00
#> 9 JFK MCO -3 -8 2013-01-01 05:57:00 2013-01-01 06:00:00
#> 10 LGA ORD -2 8 2013-01-01 05:58:00 2013-01-01 06:00:00
#> # ℹ 328,053 more rows
#> # ℹ 3 more variables: arr_time <dttm>, sched_arr_time <dttm>, air_time <dbl>
# 86400秒 = 1天,由于横轴是日期时间型数据,1代表1秒
# 以10分钟为宽度,汇总2013年1月1日起飞航班的频数
flights_dt %>%
filter(dep_time < ymd(20130102)) %>%
ggplot(aes(dep_time)) +
geom_freqpoly(binwidth = 600) # 600秒 = 10分钟
如果想要提取出日期中的独立成分,可以使用以下访问器函数: year()、 month()、 mday()(一个月中的第几天)、 yday()(一年中的第几天)、 wday()(一周中的第几天)、 hour()、minute() 和 second():
#> [1] 2016
#> [1] 7
#> [1] 8
#> [1] 190
#> [1] 6
对于 month() 和 wday() 函数,你可以设置 label = TRUE 来返回月份名称和星期数的缩写,还可以设置 abbr = FALSE 来返回全名:
# 注意,lubridate中的这两个函数会被data.table包的同名函数覆盖
# 因此,用到这个功能的时候,不能用data.table包
lubridate::month(datetime, label = TRUE)
#> [1] Jul
#> 12 Levels: Jan < Feb < Mar < Apr < May < Jun < Jul < Aug < Sep < ... < Dec
#> [1] Friday
#> 7 Levels: Sunday < Monday < Tuesday < Wednesday < Thursday < ... < Saturday
应用于flights数据:
flights_dt %>%
mutate(wday = lubridate::wday(dep_time, label = TRUE)) %>%
ggplot(aes(x = wday)) + geom_bar()
# 查看一小时内每分钟的平均出发延误
flights_dt %>%
mutate(minute = minute(dep_time)) %>%
group_by(minute) %>%
summarize(avg_delay = mean(arr_delay, na.rm = TRUE),
n = n()) %>%
ggplot(aes(minute, avg_delay)) +
geom_line()
通过 floor_date()、 round_date() 和 ceiling_date() 函数将日期舍入到临近的一个时间单位。
#> [1] "2016-07-08 12:34:56 UTC"
#> [1] "2020-07-08 12:34:56 UTC"
#> [1] "2020-01-08 12:34:56 UTC"
除了原地修改,你还可以通过 update() 函数创建一个新日期时间,这样也可以同时设置多个成分。如果设置的值过大,那么可以自动向后滚动。
#> [1] "2020-02-02 02:34:56 UTC"
#> [1] "2015-03-02"
#> [1] "2015-02-17 16:00:00 UTC"
flights_dt %>%
mutate(dep_hour = update(dep_time, yday = 1)) %>%
ggplot(aes(dep_hour)) +
geom_freqpoly(binwidth = 300)
#> Time difference of 16102 days
#> [1] "difftime"
#> Time difference of 16102 days
#> Time difference of 2300.286 weeks
#> Time difference of 386448 hours
用difftime数据类型构造duration
#> [1] "1391212800s (~44.08 years)"
构造时期的系列函数(都有”d”前缀和”s”后缀):
#> [1] "15s"
#> [1] "600s (~10 minutes)"
#> [1] "43200s (~12 hours)" "86400s (~1 days)"
#> [1] "0s" "86400s (~1 days)" "172800s (~2 days)"
#> [4] "259200s (~3 days)" "345600s (~4 days)" "432000s (~5 days)"
#> [1] "1814400s (~3 weeks)"
#> [1] "31557600s (~1 years)"
可以对duration进行加法和乘法操作,时期也可以与日期型数据相加或相减,仍然得到日期型:
#> [1] "38869200s (~1.23 years)"
#> [1] "Date"
#> [1] "POSIXct" "POSIXt"
lubridate 提供了阶段对象。阶段也是一种时间间隔,但它不以秒为单位;相反,它使用”人工”时间,比如日和月,这使得它们使用起来更加直观。
构造阶段的系列函数(只有”s”后缀):
#> [1] "15S"
#> [1] "10M 0S"
#> [1] "12H 0M 0S" "24H 0M 0S"
#> [1] "7d 0H 0M 0S"
#> [1] "1m 0d 0H 0M 0S" "2m 0d 0H 0M 0S" "3m 0d 0H 0M 0S" "4m 0d 0H 0M 0S"
#> [5] "5m 0d 0H 0M 0S" "6m 0d 0H 0M 0S"
#> [1] "21d 0H 0M 0S"
#> [1] "1y 0m 0d 0H 0M 0S"
可以对阶段进行加法和乘法操作:
#> [1] "60m 10d 0H 0M 0S"
#> [1] "50d 25H 2M 0S"
阶段可以和日期相加。与时期相比,阶段更容易符合我们的预期,因为它自动考虑了历法的种种规则:
#> [1] "2016-12-31 06:00:00 UTC"
#> [1] "2017-01-01"
阶段的一年years(1)到底是365天还是366天是不确定的,因此有了新的类:区间。区间是带有起点的时期,这使得你可以确切地知道它的长度。
#> [1] "2024-11-14"
#> [1] 366
如果只关心物理时间,那么就使用时期;如果还需要考虑人工时间,那么就使用阶段;如果需要找出人工时间范围内有多长的时间间隔,那么就使用区间。
为了避免混淆, R 使用国际标准 IANA 时区。这些时区使用统一带有”/“的命名方式,一般的形式为”< 大陆 >/< 城市 >“(存在例外,因为不是所有城市都位于一块大陆)。如”America/New_York”、“Europe/Paris”和”Pacific/Auckland”。之所以使用城市名,是因为IANA 数据库必须记录十年间的时区,而在十年时间中,国家更名(或分裂)的情况非常多,但城市名是基本保持不变的。
Sys.timezone() 函数找出你的当前时区。OlsonNames() 函数来查看完整的时区名称列表。
#> [1] "Asia/Shanghai"
#> [1] "Africa/Abidjan" "Africa/Accra" "Africa/Addis_Ababa"
#> [4] "Africa/Algiers" "Africa/Asmara" "Africa/Asmera"
在 R 中,时区是日期时间型数据的一个属性,仅用于控制输出。例如,以下 3 个对象表示的是同一时刻:
#> [1] "2015-06-01 12:00:00 EDT"
#> [1] "2015-06-01 18:00:00 CEST"
#> [1] "2015-06-02 04:00:00 NZST"
#> [1] "2015-06-01 12:00:00 EDT" "2015-06-01 12:00:00 EDT"
#> [3] "2015-06-01 12:00:00 EDT"
#> [1] "2015-06-02 CST" "2015-06-02 CST" "2015-06-02 CST"
#> [1] "2015-06-01 12:00:00 CST" "2015-06-01 12:00:00 CST"
#> [3] "2015-06-01 12:00:00 CST"