【问题标题】:R drops hours, minutes, and seconds from dateR 从日期中删除小时、分钟和秒
【发布时间】:2017-06-10 01:24:18
【问题描述】:

在将数据帧转换为 xts 时,我意识到格式化程序有问题。这是一个示例数据框:

effective_date         price
"1990-01-01"  "100"
"1990-01-02 00:05:00"  "200"

这是我使用的包的示例输出。

将其转换为 xts 很简单

xts(df["price"], order_by=as.POSIXct(df["effective_date"], format="%Y-%m-%d %H:%M:%S")

但是这个错误,说NAs不能在行名中,结果是:

<NA>       100
1990-01-02 00:05:00  200

显然xts 无法弄清楚如何处理那里的奇怪约会(午夜),它不会强迫它。

如果我将 tz="UTC" 添加到 as.POSIXct 它将不起作用。此外,as.POSIXlt 在这里也没有任何改变。

如何将午夜日期强制转换为正确格式?

【问题讨论】:

    标签: r datetime time xts


    【解决方案1】:

    1) 要获得"POSIXct" 日期时间向量,请尝试将每个日期时间分别转换为"POSIXct",然后将它们连接在一起:

    do.call("c", lapply(df$effective_date, as.POSIXct))
    

    2) 另一个更短且速度更快的基本解决方案是以下解决方案,它依赖于as.POSIXct 将在最后忽略垃圾的事实。

    as.POSIXct(paste(df$effective, "00:00:00"))
    

    【讨论】:

    • 使用 Base R 的起首部分,但速度较慢(请参阅我的回答),并且输入时仅限于 ISO 格式。
    【解决方案2】:

    两个问题:

    1) 您不能将日期单独解析为具有给定格式的 POSIXct:

    R> as.POSIXct(c("2017-01-02", "2017-01-03 04:05:06"), format="%Y-%m-%d %H:%M:%S")
    [1] NA                        "2017-01-03 04:05:06 CST"
    R>
    

    2) 但是,您可以使用 anytime() 函数来执行此操作:

    R> anytime::anytime(c("2017-01-02", "2017-01-03 04:05:06"))
    [1] "2017-01-02 00:00:00 CST" "2017-01-03 04:05:06 CST"
    R> 
    

    一旦有了POSIXct,就很容易形成xts

    另请注意,您有拼写错误:您需要在列指示符之前使用逗号:df[, "price"]

    编辑: 有点厌倦了@42 关于 Gabor 的(好的)解决方案“主导”这个解决方案的评论,所以这里是最低基准:

    R> library(microbenchmark)
    R> v <- c("2017-01-02", "2017-01-03 04:05:06")
    R> library(anytime)
    R> print(microbenchmark(anytime(v), do.call("c", lapply(v, as.POSIXct))), digits=3)
    Unit: microseconds
                                    expr   min    lq  mean median    uq   max neval cld
                              anytime(v)  33.6  36.8  42.1   45.6  46.6  80.7   100  a 
     do.call("c", lapply(v, as.POSIXct)) 571.5 579.1 586.4  586.8 589.5 695.7   100   b
    R> 
    

    简而言之,“不是真的”。它只使用 R Base,这是一个优点,说它是 a) 更难阅读和理解,b) 更有限,因为它处理 exactly one 格式(ISO 风格)和 c) 它是大约慢了 13 倍

    【讨论】:

    • 对错字更正的强制投票。 anytime 非常整洁。我能想到的最好的 R 基础是 do.call(pmax, c(Map(as.POSIXct, dat["effective_date"], format=list("%Y-%m-%d %H:%M:%S", "%Y-%m-%d")), na.rm=TRUE) )
    • 我认为 G.Grothendeick 的基本解决方案将主导这一解决方案。
    【解决方案3】:

    lubridate 的大多数解析函数都有一个truncated 参数,该参数接受一个数字,表示可以从末尾丢失的元素的数量。缺少的元素将被零替换。

    手头数据示例:

    lubridate::ymd_hms(c("2017-01-02", "2017-01-03 04:05:06"), truncated = 3)
    ## [1] "2017-01-02 00:00:00 UTC" "2017-01-03 04:05:06 UTC"
    

    【讨论】:

    • 嗯,但这仍然不如anytime::anytime() 因为你必须提供truncated 参数
    • 它需要更多的努力,是的,但如果您希望此类日期失败并出现警告,它也可以让您更好地控制。
    • 嗯,零仍然小于一。我的解决方案更通用,因为它会在更少的奇怪输入场景下失败,并且比这个需要更少的手持和操作员检查。哦,好吧。
    • 我不确定我是否明白你的意思。是的,anytime 令人印象深刻(就像您的其他工作一样!),并且对用户的要求很少。不过,这并不意味着任何其他答案都是无效的; SO不是零和游戏。包开发也不是。
    【解决方案4】:

    假设您需要时间戳,请使用以下内容进行预处理:

    temp <- c("1990-01-01", "1990-01-02 00:05:00")
    
    # match a date string at the end of string (indicated by $). Replace
    # with the full string (indicated by \\1 and 00:00:00
    temp2 <- gsub("(\\d{4}\\-\\d{2}\\-\\d{2}$)", "\\1 00:00:00", temp)
    
    # [1] "1990-01-01 00:00:00" "1990-01-02 00:05:00"
    

    【讨论】:

    • 这很粗糙。在尝试解析日期或转换日期时,我通常建议不要使用正则表达式。请参阅我的答案以获得更好的方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多