转换为 日期类型 从 2017 Apr 到 2017-04-01 in r.



我正在尝试将以下内容转换为 R 中的数据对象,以便它是每月的第一天"2017-04-01"、"2015,-07-01"、"2014-09-01"等。

我尝试拆分列并使用:

mutate(numeric_month = match(month, month.abb))

数据

c("2017 Apr", "2015 Jul", "2014 Sep", "2014 Sep", "2016 Jun", "2015 Mar", "2016 Jul", "2017 Jan", "2014 Dec")

首先:这不是为了替代@wusel的答案,我从中借用了truncated=1; 更重要的是,这是为了增强和告知决策。虽然lubridate和相关包通常是一个快速答案,但了解基本 R 方法也可能很好(有时甚至是首选(。


有几个软件包可以很好地"猜测"格式,包括 lubridateanytime .这些通常处理(足够好(变量格式,这在人工生成的数据中很常见。

有时,它们的功能更快,但并非总是如此。例如,下面的基本 R 方法在包含 9 个元素的样本 vec 时速度提高了 100 倍。 lubridate::ymd直到大约 9000 个元素才能达到奇偶校验,此时它与基本 R 解决方案一样快。

如果你担心外部库依赖项,那么基本 R 解决方案可能就足够了:

vec <- c("2017 Apr", "2015 Jul", "2014 Sep", "2014 Sep", "2016 Jun", "2015 Mar", "2016 Jul", "2017 Jan", "2014 Dec")
as.Date(paste(vec, "01"), format = "%Y %b %d") 
# [1] "2017-04-01" "2015-07-01" "2014-09-01" "2014-09-01" "2016-06-01"
# [6] "2015-03-01" "2016-07-01" "2017-01-01" "2014-12-01"

性能可能是一个问题,外部库并不总是比基本 R 启动得更快。例如,请参阅下面的基准测试。(为了简洁起见,我省略了除第一个之外的所有microbenchmark调用。

ovec <- vec # for easy replication
vec <- ovec # unmodified, length 9
microbenchmark::microbenchmark(
  base=as.Date(paste(vec, "01"), format = "%Y %b %d"),
  lub=lubridate::ymd(vec, truncated=1),
  any=anytime::anydate(vec)
)
# Unit: microseconds
#  expr    min      lq     mean  median      uq    max neval
#  base   24.8   32.75   44.030   40.65   48.45   96.6   100
#   lub 1930.2 2220.15 2493.421 2470.70 2600.55 3988.9   100
#   any  843.4 1028.55 1100.802 1064.70 1117.35 1786.7   100
vec <- rep(ovec, 100) # length 900
# Unit: milliseconds
#  expr     min       lq      mean   median      uq     max neval
#  base  1.0186  1.03205  1.077106  1.05280  1.0821  1.7377   100
#   lub  3.7256  3.85880  4.078732  3.99555  4.1191  7.6760   100
#   any 80.2832 81.01845 81.866035 81.38680 82.0539 94.5261   100
vec <- rep(ovec, 1000) # length 9000
# Unit: milliseconds
#  expr      min        lq      mean    median        uq       max neval
#  base  10.0675  10.21355  10.54913  10.34485  10.61695   13.6982   100
#   lub   9.9044  10.17945  10.57318  10.29240  10.57785   13.3987   100
#   any 809.8678 820.55190 842.60012 825.04555 845.02495 1132.2419   100

(我可能对anytime做错了什么,考虑到输入,我原本预计它会飙升得更快一些。如果我遗漏了什么,我会提出建议来改进这种比较。

如您所见,当数据长度为 9000 时,lubridate解决方案的运行时间大致相同。对于咯咯笑声,在 10 倍时,lubridate::ymd解决方案的效果要好得多(省略anytime(:

vec <- rep(ovec, 10000)
# Unit: milliseconds
#  expr     min        lq      mean   median        uq      max neval
#  base 99.1428 101.35455 111.49082 106.3730 119.97595 183.0905   100
#   lub 36.0184  37.09255  42.45397  40.2352  46.85875  74.5182   100

这很容易通过lubridatetruncated参数来实现。

library(magrittr)
c("2017 Apr", "2015 Jul", "2014 Sep", "2014 Sep", "2016 Jun", "2015 Mar", "2016 Jul", "2017 Jan", "2014 Dec") %>% 
  lubridate::ymd(truncated = 1)

编辑:关于truncated参数的说明:

lubridate有很多功能,您可以使用它们轻松定义日期/日期时间信息的存储顺序。但是,它并不涵盖所有可能的情况。例如,您的特定情况没有ym()功能,但截断基本上表示可以丢失多少日期部分。

如果您的数据不一致,有时提供的信息较少,这也很有帮助。检查此处的区别,无论您将truncated设置为 1 还是2

c("2017 Apr", "2015 Jul", "2014 ", "2014 Sep", "2016 Jun", "2015 Mar", "2016 Jul", "2017 Jan", "2014 Dec") %>% 
  lubridate::ymd(truncated = 2)

相关内容

最新更新