【问题标题】:How can I change character class date variables to POSIXlt class when there are multiple date formats?当有多种日期格式时,如何将字符类日期变量更改为 POSIXlt 类?
【发布时间】:2016-05-04 05:19:47
【问题描述】:

我正在努力转换许多不同格式类型的字符类日期(例如,yyyy/mm/dd;mm/dd/yyyy;yyyy-mm-dd;mm-dd-yyyy;yy-mm-dd; mm-dd-yy; 等)到 POSIXlt 类。理想情况下,我想将所有birth_dates 转换为具有yyyy/mm/dd 格式的POSIXlt 类(参见下面的示例数据)。在 R 中是否有任何简单的方法可以做到这一点?:

   id  birth_date  start_date  age
  102   08/09/1993  2013/09/01 20
  103   1995-02-21  2013/09/01 18
  104   01-15-94    2013/09/01 19
  105   88-12-30    2013/09/01 24

这是我迄今为止一直在做的事情。不幸的是,考虑到原始日期格式的所有不同方式,这似乎不起作用(我最终得到的 NA 比应该有的多):

  library(lubridate)
  data$birth_date1<-as.Date(data$birth_date,format="%Y-%m-%d") #Convert character class to date class
  data$birth_date2<-ymd(swc3$birth_date1) #Convert date class to POSIXlt class using lubridate pkg

【问题讨论】:

  • 您打算如何处理不明确的日期(即“01-02-03”)?人类不可能知道正确答案是什么。
  • 你可以从lubridate使用parse_date_time
  • 我觉得这是一个数据清理问题,而不是编程问题。解决方案可能会涉及一些丑陋的正则表达式和临时列。

标签: r date datetime lubridate


【解决方案1】:

这太可怕了。不过可能会更糟。至少那里有分隔符,比如“-”和“/”。

简答

是的,有一种简单的方法可以在 R 中解析它。将parse_date_time() 分别应用于每个出生日期,给它一个不错的orders 列表以供选择,并仔细设置猜测的顺序。完成后,您需要将“整数时间”转换为有用的时间。

详情请参阅长答案。

长答案

这就是lubridate 包具有parse_date_time() 的原因。但也有问题。让我们看看:

require(lubridate)
# WRONG! doesn't work as intended.
as.Date(
    parse_date_time(data$birth_date, 
                    orders=c("ymd", "mdy", "mdY", "Ymd")
    )
)  
 [1] "1993-08-09" "1995-02-21" "1994-01-15" "0088-12-30"

看起来不错,除了最后一个。怎么回事?

parse_date_time() 正在选择一组“最合适”的顺序和格式以在解析日期时使用,最后一个元素是奇数。

要使这项工作按预期进行,您需要将parse_date_time() 逐个应用于每个日期,因为显然每个日期格式或多或少是随机选择的。这会比较慢,但会给出更有用的答案。

# RIGHT. Some conversion of results required.
parsed <- sapply(data[,"birth_date"],
                 parse_date_time,
                 orders=c("ymd", "mdy", "mdY", "Ymd") )
parsed
08/09/1993 1995-02-21   01-15-94   88-12-30 
744854400  793324800  758592000  599443200 

好的,这些看起来像 Unix 时间的整数,它们是 parse_date_time() 产生的 unclass()'d 版本。没有一个是负面的,所以它们一定都发生在 1970 年之后。这是令人鼓舞的。转换:

# Conversion of results
parsed <- as.POSIXct(parsed, origin="1970-01-01", tz = "GMT")
as.Date(parsed)
08/09/1993   1995-02-21     01-15-94     88-12-30 
"1993-08-09" "1995-02-21" "1994-01-15" "1988-12-30" 

lubridateparse_date_time() 非常擅长他们的工作。

由于您要求的是 POSIXlt,而不是日期类型:

as.POSIXlt(parsed)
                08/09/1993                 1995-02-21 
"1993-08-09 10:00:00 AEST" "1995-02-21 11:00:00 AEDT" 
                 01-15-94                   88-12-30 
"1994-01-15 11:00:00 AEDT" "1988-12-30 11:00:00 AEDT" 

虽然我个人更喜欢只在实际时间不重要的情况下约会;假设这些都发生在 UTC 午夜,并转换为我的时区(澳大利亚东部)。

【讨论】:

    猜你喜欢
    • 2015-01-27
    • 2019-11-04
    • 2021-11-22
    • 2022-07-04
    • 2020-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多