【问题标题】:R: how to filter a timestamp by hour and minute?R:如何按小时和分钟过滤时间戳?
【发布时间】:2017-05-18 19:42:56
【问题描述】:

我正在为以下示例而苦苦挣扎

time = c('2013-01-03 21:59:21.549', '2013-01-04 22:00:21.549', '2013-01-05 22:01:21.222', '2013-01-06 22:06:23.559' )
value = c(1,2,3,4)

data <- data_frame(time, value)
data <-data %>%  mutate(time = ymd_hms(time))

> data
# A tibble: 4 × 2
                 time value
               <dttm> <dbl>
1 2013-01-03 21:59:21     1
2 2013-01-04 22:00:21     2
3 2013-01-05 22:01:21     3
4 2013-01-06 22:06:23     4

除了每天只在21:5922:01(包括)之间进行观察之外,我如何编写dplyr::filter 语句?

单独使用hour(time)minute(time) 在这里似乎效果不佳。

我错过了什么吗?

预期输出:仅第 1,2 和 3 行。 谢谢!

【问题讨论】:

  • 您可以减去日期(将所有内容标准化为 1960-01-01 吗?然后使用过滤器?

标签: r datetime dplyr lubridate


【解决方案1】:

2019 年来了! 这是使用as.hms 的更好(更简单)的解决方案。 tz 参数是强制性的。

    time_str = c('2013-01-03 21:59:21.549', '2013-01-04 22:00:21.549', '2013-01-05 
    22:01:21.222', '2013-01-06 22:06:23.559' )
    value = c(1,2,3,4)
    data <- tibble(time_str, value)

    data %>%  mutate(timestamp_utc = ymd_hms(time_str, tz = 'UTC'),
                     timestamp_est = with_tz(timestamp_utc, 'America/New_York'),
                            time_est = as.hms(timestamp_est, tz = 'America/New_York')) %>% 
      filter(time_est >= hms::as.hms('16:59:00', tz = 'America/New_York'),
             time_est <= hms::as.hms('17:01:00', tz = 'America/New_York'))

会做好的

# A tibble: 2 x 5
  time_str                value timestamp_utc           timestamp_est           time_est 
  <chr>                   <dbl> <dttm>                  <dttm>                  <time>   
1 2013-01-03 21:59:21.549     1 2013-01-03 21:59:21.549 2013-01-03 16:59:21.549 16:59.549
2 2013-01-04 22:00:21.549     2 2013-01-04 22:00:21.549 2013-01-04 17:00:21.549 17:00.549

【讨论】:

  • 这太棒了,经过多次磕磕绊绊,我找到了你的问题和答案,它适用于我需要的东西。谢谢。
  • 谢谢兄弟。如果对您有用,您可以对问题和答案进行投票:)
  • as.hms() 已被 as_hms() 取代,它不再是通用的,也没有 tz 参数。它还使用参数的时区进行转换,而不是当前系统的时区。如有必要,在转换之前更改时区,例如使用 lubridate::with_tz()。
【解决方案2】:

您从lubridate 中提到了hourminute 不起作用,但我不知道为什么。这不行吗?

filter(data, 
    (hour(time) == 21 & minute(time) == 59) | 
    (hour(time) == 22 & minute(time) <= 1)
)

另一种方法是获取一天中经过的秒数,并与您想要的限制对应的秒数进行比较。一天中经过的秒数计算为以一天中的秒数为模的总秒数:as.numeric(data$time) %% (60 * 60 * 24)。直到(分钟开始)21:59 的秒数是60 * 60 * 21 + 60 * 59,直到(分钟结束)22:01 的秒数是60 * 60 * 22 + 60 + 59。结合一切,

filter(data, between(as.numeric(time) %% (60 * 60 * 24),
                     60 * 60 * 21 + 60 * 59,
                     60 * 60 * 22 + 60 + 59
             )
 )

【讨论】:

  • 嘿等一下!让我想想:)
  • 好的,用您的解决方案在19:5923:38 之间进行过滤怎么样? :D
  • 在这种情况下,您必须将过滤条件更改为(hour(time) == 19 &amp; minute(time) == 59) | between(hour(time), 20, 22) | (hour(time) == 23 &amp; minute(time) &lt;= 38))。我同意它有点难看。我将发布另一种使用秒比较的方法
【解决方案3】:

另一个想法如下。您可以使用小时、分钟和秒来创建数值向量。您可以使用format() 提取它们并将字符转换为数字。然后,您使用两个表示您想要的时间范围的数字(即 215900、220100)对数据进行子集化。

library(dplyr)

data %>%
mutate(foo = as.numeric(format(time, "%H%M%S"))) %>%
filter(between(foo, 215900, 220100)) %>%
select(-foo)

#                 time value
#               <dttm> <dbl>
#1 2013-01-03 21:59:21     1
#2 2013-01-04 22:00:21     2

【讨论】:

  • 听起来不错,只要数字表示在任何时候都反映了字符串表示。换句话说,04:34:23 应该是 43423?
  • @Noobie 将字符转换为数字时,将删除第一个零。所以,我认为这不是问题。当你的时间戳在上午和下午时,我的想法不是一个好的选择。
【解决方案4】:

我想这可以解决你的问题:

library(dplyr) 

result <- data %>%  
  mutate(time2 = format(time, format="%H:%M:%S")) %>%
  filter(time2 >= "21:59:00" & time2 < "22:02:00") %>%
  select(-time2)

【讨论】:

  • 不错!但我唯一担心的是time2 是一个字符。我们确定比较time2 &gt;= "21:59:00" 一直有意义吗(啊啊)
  • 到目前为止,我没有遇到像这样的过滤问题。总能得到我想要的结果。
  • @Noobie 参见例如this answer 字符比较。
  • 谢谢哥们。不过我很害怕This is a really dangerous approach 部分。
【解决方案5】:

另一种过滤时间窗口的方法可以通过将时间戳转换为分钟或秒(时间设置为 0000 - 2400),将其存储在新变量中并使用新变量进行过滤。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-01-17
    • 2014-03-12
    • 2021-07-02
    • 2017-10-22
    • 1970-01-01
    • 1970-01-01
    • 2013-10-08
    • 1970-01-01
    相关资源
    最近更新 更多