学习tidyverse – Dates and times(1)

时间:2021-6-7 作者:qvyue

本章将展示如何在 R 中使用日期和时间。乍一看,日期和时间似乎很简单。在日常生活中一直在使用它们,它们似乎不会引起太多混乱。但是,对日期和时间了解得越多,它们似乎就越复杂。请尝试以下三个看似简单的问题:

  • 每年有365天吗?
  • 每天有24小时吗?
  • 每分钟有 60 秒吗?
    我确定不是每年都有 365 天,但是您知道确定一年是否为闰年的完整规则吗? (它分为三个部分。)您可能还记得世界上许多地方都使用夏令时 (DST),因此有些日子有 23 小时,有些日子有 25 小时。您可能不知道有些分钟有 61 秒,因为因为地球的自转正在逐渐减慢,所以不时添加闰秒。

日期和时间很困难,因为它们必须调和两个物理现象(地球自转及其绕太阳公转)和整个地缘政治现象,包括月份,时区和DST。本章不会教你关于日期和时间的每一个细节,但它会给你一个坚实的实践技能基础,帮助你解决常见的数据分析挑战。
本章将重点介绍 lubridate 包,它可以更轻松地在 R 中处理日期和时间。 lubridate 不是核心 tidyverse 的一部分,因为只有在处理日期/时间时才需要它。 我们还需要 nycflights13 来获取练习数据。

library(tidyverse)

library(lubridate)
library(nycflights13)

1. Creating date/times

有三种类型的日期/时间数据指的是时间:
data: 日期。Tibbles 将其打印为 date

time: 时间。Tibbles 将此打印为 time

data-time:日期时间。它唯一地标识了一个瞬间(通常到最近的秒)。 Tibbles 将其打印为 dttm

在本章中,我们将只关注日期和日期时间,要获取当前日期或日期时间,可以使用 today()now()

today()
#> [1] "2020-10-09"
now()
#> [1] "2020-10-09 11:59:37 UTC"

否则,可能会通过三种方式创建日期/时间:

  • 从一个字符串。
  • 来自各个日期时间组件。
  • 从现有的日期/时间对象。
    它们的工作方式如下。
(1) From strings

日期/时间数据通常以字符串形式出现。 您已经看到了一种将字符串解析为日期时间中的日期时间的方法。 另一种方法是使用 lubridate 提供的助手。 一旦您指定了组件的顺序,它们就会自动计算出格式。 要使用它们,请确定日期中出现的年、月和日的顺序,然后按相同顺序排列“y”、“m”和“d”。 这为您提供了将解析您的日期的 lubridate 函数的名称。 例如:

ymd("2017-01-31")
#> [1] "2017-01-31"
mdy("January 31st, 2017")
#> [1] "2017-01-31"
dmy("31-Jan-2017")
#> [1] "2017-01-31"

这些功能也采用未加引号的数字。 这是创建单个日期/时间对象的最简洁的方法,因为您在过滤日期/时间数据时可能需要。 ymd() 简短而明确:

ymd(20170131)
#> [1] "2017-01-31"

ymd()创建日期。 要创建日期时间,请在解析函数的名称中添加下划线和“h”、“m”和“s”中的一个或多个:

ymd_hms("2017-01-31 20:11:59")
#> [1] "2017-01-31 20:11:59 UTC"
mdy_hm("01/31/2017 08:01")
#> [1] "2017-01-31 08:01:00 UTC"

您还可以通过提供时区来强制从日期创建日期时间:

ymd(20170131, tz = "UTC")
#> [1] "2017-01-31 UTC"
(2) From individual components

有时您会将日期时间的各个组件分布在多个列中,而不是单个字符串。 这是我们在航班数据中的内容:

flights %>% 
  select(year, month, day, hour, minute)
#> # A tibble: 336,776 x 5
#>    year month   day  hour minute
#>   
#> 1  2013     1     1     5     15
#> 2  2013     1     1     5     29
#> 3  2013     1     1     5     40
#> 4  2013     1     1     5     45
#> 5  2013     1     1     6      0
#> 6  2013     1     1     5     58
#> # … with 336,770 more rows

要从此类输入创建日期/时间,请使用 make_date() 表示日期,或使用 make_datetime() 表示日期时间:

flights %>% 
  select(year, month, day, hour, minute) %>% 
  mutate(departure = make_datetime(year, month, day, hour, minute))
#> # A tibble: 336,776 x 6
#>    year month   day  hour minute departure          
#>                
#> 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
#> # … with 336,770 more rows

让我们对航班的四个时间列中的每一个都做同样的事情。 时间以稍微奇怪的格式表示,因此我们使用模数算法来提取小时和分钟组件。 创建日期时间变量后,我将重点关注我们将在本章其余部分中探讨的变量。

make_datetime_100 % 
  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 x 9
#>   origin dest  dep_delay arr_delay dep_time            sched_dep_time     
#>                
#> 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
#> # … with 328,057 more rows, and 3 more variables: arr_time ,
#> #   sched_arr_time , air_time 

有了这些数据,我可以可视化一年中出发时间的分布:

flights_dt %>% 
  ggplot(aes(dep_time)) + 
  geom_freqpoly(binwidth = 86400) # 86400 seconds = 1 day
学习tidyverse - Dates and times(1)

或在一天内:

flights_dt %>% 
  filter(dep_time % 
  ggplot(aes(dep_time)) + 
  geom_freqpoly(binwidth = 600) # 600 s = 10 minutes
学习tidyverse - Dates and times(1)

请注意,当您在数字上下文中(如在直方图中)使用日期时间时,1 表示 1 秒,因此 86400 的 binwidth 表示一天。 对于日期,1 表示 1 天。

(3) From other types

您可能需要在日期时间和日期之间切换。 这就是 as_datetime() 和 as_date() 的工作:

as_datetime(today())
#> [1] "2020-10-09 UTC"
as_date(now())
#> [1] "2020-10-09"

有时你会得到日期/时间作为来自“Unix Epoch”,1970-01-01 的数字偏移量。 如果偏移量以秒为单位,则使用 as_datetime(); 如果以天为单位,请使用 as_date()。

as_datetime(60 * 60 * 10)
#> [1] "1970-01-01 10:00:00 UTC"
as_date(365 * 10 + 2)
#> [1] "1980-01-01"

参考:https://r4ds.had.co.nz/dates-and-times.html

声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:qvyue@qq.com 进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。