我正在尝试将以下内容转换为 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 方法也可能很好(有时甚至是首选(。
有几个软件包可以很好地"猜测"格式,包括 lubridate
和 anytime
.这些通常处理(足够好(变量格式,这在人工生成的数据中很常见。
有时,它们的功能更快,但并非总是如此。例如,下面的基本 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
这很容易通过lubridate
和truncated
参数来实现。
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)