如何从POSIXct范围子集POSIXct

时间:2019-06-07 19:31:52

标签: r dplyr tidyverse lubridate posixct

我很难弄清楚如何提取在另一个事件(在我的情况下为字母)中发生的事件的时间。我希望有人可以帮助我! 简而言之:我希望bb tibble的行的开始或结束或两者(开始和结束)时间都在aa记录的范围内。 最终目标是找出字母在小语中出现了多少次。 请让我知道是否需要更多说明! 预先谢谢你!

aa <- tibble(
           start = as.POSIXct(c("2019-05-02 07:08:49", "2019-05-02 07:09:21",
                                    "2019-05-02 07:09:41", "2019-05-02 07:10:05",
                                    "2019-05-02 07:24:52", "2019-05-02 07:28:50",
                                    "2019-05-02 07:29:23", "2019-05-02 07:30:16",
                                    "2019-05-02 07:33:13", "2019-05-02 07:33:43",
                                    "2019-05-02 07:35:31", "2019-05-02 07:36:29",
                                    "2019-05-02 07:38:14", "2019-05-02 07:43:26",
                                    "2019-05-02 07:44:59", "2019-05-02 07:53:45",
                                    "2019-05-02 07:54:28")),
           end = as.POSIXct(c("2019-05-02 07:09:29", "2019-05-02 07:10:02",
                                    "2019-05-02 07:10:17", "2019-05-02 07:10:40",
                                    "2019-05-02 07:29:10", "2019-05-02 07:29:32",
                                    "2019-05-02 07:30:35", "2019-05-02 07:30:53",
                                    "2019-05-02 07:33:48", "2019-05-02 07:34:18",
                                    "2019-05-02 07:36:06", "2019-05-02 07:38:34",
                                    "2019-05-02 07:38:49", "2019-05-02 07:45:19",
                                    "2019-05-02 07:45:35", "2019-05-02 07:54:20",
                                    "2019-05-02 07:55:03")))

bb <- tibble(letters = sample(letters[1:4], 12, TRUE), 
             started = as.POSIXct(c("2019-05-02 07:30:23", "2019-05-02 07:30:56",
                                      "2019-05-02 07:31:29", "2019-05-02 07:31:55",
                                      "2019-05-02 07:32:22", "2019-05-02 07:32:48",
                                      "2019-05-02 07:33:14", "2019-05-02 07:44:36",
                                      "2019-05-02 07:45:11", "2019-05-02 07:45:36",
                                      "2019-05-02 07:46:01", "2019-05-02 07:48:14"
                                     )),
             stopped = as.POSIXct(c("2019-05-02 07:30:56", "2019-05-02 07:31:29",
                                    "2019-05-02 07:31:55", "2019-05-02 07:32:22",
                                    "2019-05-02 07:32:48", "2019-05-02 07:33:14",
                                    "2019-05-02 07:33:40", "2019-05-02 07:45:10",
                                    "2019-05-02 07:45:36", "2019-05-02 07:46:01",
                                    "2019-05-02 07:46:25", "2019-05-02 07:48:48")))

2 个答案:

答案 0 :(得分:2)

这是一种使用Fuzzyjoin的方法,可让您指定bb$started必须为> = {aa$start,而bb$stopped <= aa$end必须为

library(fuzzyjoin); 
fuzzy_inner_join(bb, aa,
                   by = c("started" = "start",
                          "stopped" = "end"),
                   match_fun = list(`>=`, `<=`)
                 )

# A tibble: 2 x 5
  letters started             stopped             start               end                
  <chr>   <dttm>              <dttm>              <dttm>              <dttm>             
1 a       2019-05-02 07:33:14 2019-05-02 07:33:40 2019-05-02 07:33:13 2019-05-02 07:33:48
2 c       2019-05-02 07:44:36 2019-05-02 07:45:10 2019-05-02 07:43:26 2019-05-02 07:45:19

答案 1 :(得分:1)

data.table包中有两个函数对此很有用。

最简单的可能是inrange函数:

使用inrange来识别bb中开始或停止的行在aa中任何行方向的起始-结束间隔内。

library(data.table)

setDT(bb)
bb[started %inrange% aa | stopped %inrange% aa]

#    letters             started             stopped
# 1:       a 2019-05-02 07:30:23 2019-05-02 07:30:56
# 2:       a 2019-05-02 07:32:48 2019-05-02 07:33:14
# 3:       c 2019-05-02 07:33:14 2019-05-02 07:33:40
# 4:       c 2019-05-02 07:44:36 2019-05-02 07:45:10
# 5:       b 2019-05-02 07:45:11 2019-05-02 07:45:36

要获取所需的计数,请按字母分组并返回出现的次数:

bb[started %inrange% aa | stopped %inrange% aa, list(count = .N), by = letters]

#   letters count
#1:       a     2
#2:       c     2
#3:       b     1

foverlaps函数也可以用于此目的;更加灵活,但涉及更多:

首先在aa和bb上设置键:

setDT(aa)
setkey(aa, start, end)
setDT(bb)
setkey(bb, started, stopped)

对foverlaps的简单调用显示了联接的结果,其中bb中的行的NA不匹配aa中的任何间隔。

foverlaps(aa, bb)

#                  start                 end letters             started             stopped
# 1: 2019-05-02 07:29:23 2019-05-02 07:30:35       a 2019-05-02 07:30:23 2019-05-02 07:30:56
# 2: 2019-05-02 07:30:16 2019-05-02 07:30:53       a 2019-05-02 07:30:23 2019-05-02 07:30:56
# 3:                <NA>                <NA>       a 2019-05-02 07:30:56 2019-05-02 07:31:29
# 4:                <NA>                <NA>       b 2019-05-02 07:31:29 2019-05-02 07:31:55
# 5:                <NA>                <NA>       d 2019-05-02 07:31:55 2019-05-02 07:32:22
# 6:                <NA>                <NA>       b 2019-05-02 07:32:22 2019-05-02 07:32:48
# 7: 2019-05-02 07:33:13 2019-05-02 07:33:48       a 2019-05-02 07:32:48 2019-05-02 07:33:14
# 8: 2019-05-02 07:33:13 2019-05-02 07:33:48       c 2019-05-02 07:33:14 2019-05-02 07:33:40
# 9: 2019-05-02 07:43:26 2019-05-02 07:45:19       c 2019-05-02 07:44:36 2019-05-02 07:45:10
# 10: 2019-05-02 07:44:59 2019-05-02 07:45:35       c 2019-05-02 07:44:36 2019-05-02 07:45:10
# 11: 2019-05-02 07:43:26 2019-05-02 07:45:19       b 2019-05-02 07:45:11 2019-05-02 07:45:36
# 12: 2019-05-02 07:44:59 2019-05-02 07:45:35       b 2019-05-02 07:45:11 2019-05-02 07:45:36
# 13:                <NA>                <NA>       c 2019-05-02 07:45:36 2019-05-02 07:46:01
# 14:                <NA>                <NA>       a 2019-05-02 07:46:01 2019-05-02 07:46:25
# 15:                <NA>                <NA>       c 2019-05-02 07:48:14 2019-05-02 07:48:48

要仅获取bb中与a的间隔匹配的行,请使用set nomatch

foverlaps(bb, aa, nomatch = NULL)

类似地,要只显示每个匹配行一次,请设置mult

foverlaps(bb, aa, nomatch = NULL, mult = "first")

#                   start                 end letters             started             stopped
# 1: 2019-05-02 07:29:23 2019-05-02 07:30:35       a 2019-05-02 07:30:23 2019-05-02 07:30:56
# 2: 2019-05-02 07:33:13 2019-05-02 07:33:48       a 2019-05-02 07:32:48 2019-05-02 07:33:14
# 3: 2019-05-02 07:33:13 2019-05-02 07:33:48       c 2019-05-02 07:33:14 2019-05-02 07:33:40
# 4: 2019-05-02 07:43:26 2019-05-02 07:45:19       c 2019-05-02 07:44:36 2019-05-02 07:45:10
# 5: 2019-05-02 07:43:26 2019-05-02 07:45:19       b 2019-05-02 07:45:11 2019-05-02 07:45:36

您可以通过对字母分组并计算行数来计算每个字母的匹配出现次数:

foverlaps(aa, bb, nomatch = NULL, mult = "first")[ , list(count = .N), by = letters]

#   letters count
#1:       a     2
#2:       c     2
#3:       b     1