【问题标题】:parse multiple date formats by index in R通过R中的索引解析多种日期格式
【发布时间】:2021-02-20 22:43:37
【问题描述】:

我正在尝试根据它们在日期向量中的位置来解析多种日期格式。在某些情况下,数据将其使用的格式从 y/m/d 转换为 y/d/m。对于像 2010/07/03 这样在 lubridate 中指定顺序的日期,这很烦人。

这是日期示例

datevec <- c("2011/07/01", "2011/07/02", "2011/07/03", "2011/02/07" )

日期是这样设置的,所以在某一行之前,日期是一种格式,而在另一行之后,日期是另一种格式,所以我试图为函数提供索引 当我尝试使用这个加上 lubridate 来解析它们时,它只返回了 3 个日期。

lapply(datevec, function(x, i) ifelse( x[i] <4,  parse_date_time(x, "%Y-%m-%d"), parse_date_time(x,"%Y-%d-%m" )) )

【问题讨论】:

  • lapply 只做一个参数,所以i 在你的匿名函数中是未定义的。此外,我怀疑x[i] 可能是多余的。你认为那里应该发生什么? lubridate::parse_date_time(datevec, c("%Y-%m-%d", "%Y-%d-%m")) 为我工作。
  • 顺便说一句,如果数据管道中较早的部分产生了诸如 2010/07/032010/03/07 之类的模棱两可的日期......是的,世界上没有任何代码会知道哪种格式合适。它是上下文相关的,基于您对自己拥有或继承的流程的了解,并且可能基于数据中的其他线索。
  • 数据的设置使得某一行之前的所有内容都是一种格式,而该行之后的所有内容都是另一种格式。如果我只是通过索引指定具有某种格式的行(在这种情况下

标签: r lubridate


【解决方案1】:

1) 如果我们将问题中的 ifelse 更改为简单的 if,那么问题中的基本思想经过适当的修改即可发挥作用。请注意,它给出了一个列表 L,所以假设我们真的想要一个向量,我们添加最后一行代码。

f <- function(x, i) if (i < 4) 
  parse_date_time(x, "ymd") else parse_date_time(x, "ydm")
L <- Map(f, datevec, seq_along(datevec), USE.NAMES = FALSE)
do.call("c", L)
## [1] "2011-07-01 UTC" "2011-07-02 UTC" "2011-07-03 UTC" "2011-02-07 UTC"

2) 在格式部分而不是日期部分使用 ifelse 并使用 as.Date 而不是 parse_date_time:

ix <- seq_along(datevec)
as.Date(datevec, ifelse(ix < 4, "%Y/%m/%d", "%Y/%d/%m"))
## [1] "2011-07-01" "2011-07-02" "2011-07-03" "2011-07-02"

3) 使用 ymd 转换前 3 个,使用 ydm 转换其余的,然后连接。

c(ymd(head(datevec, 3)), ydm(tail(datevec, -3)))
## [1] "2011-07-01" "2011-07-02" "2011-07-03" "2011-07-02"

4) 或仅使用基本 R:

c(as.Date(head(datevec, 3)), as.Date(tail(datevec, -3), "%Y/%d/%m"))
## [1] "2011-07-01" "2011-07-02" "2011-07-03" "2011-07-02"

5) 另一种方法是使用字符串操作转换较晚的日期,使所有日期的格式相同,然后使用 as.Date 或 ymd:

ix <- seq_along(datevec)
swap <- sub("(..)/(..)$", "\\2/\\1", datevec)
as.Date(ifelse(ix < 4, datevec, swap))
## [1] "2011-07-01" "2011-07-02" "2011-07-03" "2011-07-02"

6) 上面的代码返回 Date 类,它更适合没有时间的日期,但如果由于某种原因你真的需要 POSIXct 使用 as.POSIXct 或者像这样使用 parse_date_time :

c(parse_date_time(head(datevec, 3), "ymd"), parse_date_time(tail(datevec, -3), "ydm"))
## [1] "2011-07-01 UTC" "2011-07-02 UTC" "2011-07-03 UTC" "2011-07-02 UTC"

【讨论】:

  • 当我运行它并使用 day() 检查结果时,它返回了 1 2 3 7,而它应该是 1 2 3 2
  • 我已经修复了它,但我没有得到你报告的内容,我得到了一个不同的错误答案。无论如何,它现在应该可以工作了,包括修复问题中的方法并修复原始方法,以便它可以在格式而不是数据上使用 ifelse。
  • 哦,有趣的是,您得到的错误答案是什么?只是好奇,因为我想调试以了解更多
  • 原来是 parse_date_time(datevec, ifelse(seq_along(datevec)
猜你喜欢
  • 2013-01-09
  • 2020-09-14
  • 1970-01-01
  • 2020-07-04
  • 1970-01-01
  • 1970-01-01
  • 2018-02-07
  • 2018-03-07
  • 1970-01-01
相关资源
最近更新 更多