【问题标题】:How to manipulate the time part of a date column?如何操作日期列的时间部分?
【发布时间】:2017-07-29 14:07:22
【问题描述】:

如何编写这段代码(hour 来自 lubridate 包)?

目标:如果 PICK_DATE 的小时部分晚于 16:00,则 ADJ_PICK_DATE 应该是第二天 03:00。如果 PICK_DATE 的小时部分早于 03:00,则 ADJ_PICK_DATE 为同一天 03:00。问题是,当不需要更改时,代码仍然会在 PICK_DATE 上增加 3 小时,即 PICK_DATE 的小时部分在 03:00 和 16:00 之间。

x$PICK_TIME <- cut(hour(x$PICK_DATE), c(-1, 2, 15, 24), c("EARLY", "OKAY", "LATE"))    
x$ADJ_PICK_DATE <- ifelse(x$PICK_TIME=="EARLY",
                          as.POSIXct(paste(format(x$PICK_DATE, "%d-%b-%Y"), "03:00"),
                                 format="%d-%b-%Y %H:%M"), x$PICK_DATE)
x$ADJ_PICK_DATE <- ifelse(x$PICK_TIME=="LATE",
                          as.POSIXct(paste(format(x$PICK_DATE+86400, "%d-%b-%Y"),
                                           "03:00"), format="%d-%b-%Y %H:%M"),
                          x$ADJ_PICK_DATE)
x$ADJ_PICK_DATE <- as.POSIXct(x$ADJ_PICK_DATE, origin = "1970-01-01")

请帮忙。

样本数据:

PICK_DATE   SHIP_DATE
01-APR-2017 00:51   02-APR-2017 06:55 AM
01-APR-2017 00:51   02-APR-2017 12:11 PM
01-APR-2017 00:51   02-APR-2017 12:11 PM
01-APR-2017 00:51   02-APR-2017 09:39 AM

【问题讨论】:

标签: r datetime lubridate posixct


【解决方案1】:

这是一个简单的、可重复的示例。根据您之前提出的问题,我必须制作一些示例数据。我建议阅读dplyrlubridate,因为它们会帮助你处理日期。

编辑:更新为使用月末日期。

library(lubridate)
library(dplyr)

df <- data.frame(pick_date = c("01-APR-2017 00:51", "02-APR-2017 08:53", "15-APR-2017 16:12", "23-APR-2017 02:04", "30-APR-2017 20:08"), ship_date = c("05-APR-2017 06:55", "09-APR-2017 12:11", "30-APR-2017 13:11", "02-MAY-2017 15:16", "05-MAY-2017 09:57"))

df %>% 
    mutate(pick_date = dmy_hm(pick_date)) %>% 
    mutate(ship_date = dmy_hm(ship_date)) %>% 
    mutate(pick_time = case_when(
        hour(pick_date) <= 3 ~ "early",
        hour(pick_date) >= 16 ~ "late",
        TRUE ~ "okay")
    ) %>% 
    mutate(new_pick_time = case_when(
        pick_time == "early" ~ hms(hours(3)),
        pick_time == "late" ~ hms(hours(3)),
        TRUE ~ hms(paste0(hour(pick_date), "H ", minute(pick_date), "M ", second(pick_date), "S")))
    ) %>% 
    mutate(temp_pick_date = case_when(
        pick_time == "early" ~ pick_date,
        pick_time == "late" ~ pick_date + days(1),
        TRUE ~ pick_date)
    ) %>% 
    mutate(new_pick_date = make_datetime(year(temp_pick_date), month(temp_pick_date), day(temp_pick_date), hour(new_pick_time), minute(new_pick_time), second(new_pick_time))) %>%
    select(-new_pick_time, -temp_pick_date)

返回

            pick_date           ship_date pick_time       new_pick_date
1 2017-04-01 00:51:00 2017-04-05 06:55:00     early 2017-04-01 03:00:00
2 2017-04-02 08:53:00 2017-04-09 12:11:00      okay 2017-04-02 08:53:00
3 2017-04-15 16:12:00 2017-04-30 13:11:00      late 2017-04-16 03:00:00
4 2017-04-23 02:04:00 2017-05-02 15:16:00     early 2017-04-23 03:00:00
5 2017-04-30 20:08:00 2017-05-05 09:57:00      late 2017-05-01 03:00:00

【讨论】:

  • @Arani 如果您提供一个简单、最小、可重复的示例(包括示例数据),将会有更多人能够为您提供帮助。这使社区更容易理解您的问题和帮助。我之所以能够提供帮助,是因为我看到了您之前的问题,因此对您的目标有了更多的了解。今后,请务必提供更多上下文和示例数据。
  • 感谢您的努力。这个问题实际上是从上一个问题中撕下来的,这就是我忘记添加数据的原因。另外,我理解需要更简单的陈述。再次感谢您的回答和建议。
  • 我遇到了在 new_pick_date 列中给出 NA 结果的月底日期问题。在最后一个case_when 中使用pick_date+86400 作为pick_time=="late" 参数可以解决该问题。
  • @Arani 很高兴这与您合作。我刚刚更新了我的答案以使用月末日期。抱歉耽搁了,正在搬家!
【解决方案2】:

所以听起来您只需要执行两个不同的算术运算,以日期时间的小时为条件?

我认为访问小时组件的最简单方法是将时间存储在POSIXlt 中。我相信“l”代表或“列表”,这使您可以将时间戳视为列表,相应地不同的时间测量是可访问的属性。

像这样:

> time <- as.POSIXlt('2017-07-29 15:12:01')
> time
[1] "2017-07-29 15:12:01 EDT"
> time$hour
[1] 15

因此,您可以编写一个函数来执行您想要的操作,并将它提供给您的日期列。因为我不太明白这个问题,所以我很难再进一步,但这里有一个骨架:

ComputeDifference <- function(time) {

     if (time$hour < 3) {
       # code to count orders between 0 and 3 "from same day 3:00"

    }
    if (time$hour > 16) {
      # code to consider late orders

    }

}

如果您输入示例数据并细化问题,也许我可以对此进行更彻底的破解。

【讨论】:

  • 鉴于初始代码中的混乱和缺乏数据,这是一个很好的答案。唯一的澄清(不是因为有什么问题,而是因为工作时间令人沮丧而且大多数人不知道差异),如果你想使用 time$hour 提取,请确保使用 POSIXlt,这在 @ 中不起作用987654325@。如果您更愿意使用 lubridate,则格式为小时(时间)以达到相同的 15。否则,这既优雅又简单!
猜你喜欢
  • 2019-07-01
  • 2012-11-23
  • 1970-01-01
  • 2012-05-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-30
相关资源
最近更新 更多