如何解决根据 dbplyr
我有一个来自 Postgresql
数据库的数据集,我有两列:
id
= 参与者的 ID
time_stamp
= 记录测量的时间戳
我需要使用 dbplyr
才能根据 time_stamp
的序列改变新列。换句话说,如果 time_stamp
是顺序的(意味着它以一分钟为间隔),这被识别为一个事件。
例如,这是我的数据集:
library(dplyr)
library(dbplyr)
library(lubridate)
mf <- memdb_frame(
id = "id001",time_stamp = c(
seq(from = as_datetime("2021-01-01 08:00:00"),to = as_datetime("2021-01-01 08:03:00"),by = "1 min"),seq(from = as_datetime("2021-01-01 08:05:00"),to = as_datetime("2021-01-01 08:08:00"),seq(from = as_datetime("2021-01-01 08:12:00"),to = as_datetime("2021-01-01 08:18:00"),by = "1 min")
)
)
mf %>%
collect() %>%
mutate(time_stamp = as_datetime(time_stamp))
#> # A tibble: 15 x 2
#> id time_stamp
#> <chr> <dttm>
#> 1 id001 2021-01-01 08:00:00
#> 2 id001 2021-01-01 08:01:00
#> 3 id001 2021-01-01 08:02:00
#> 4 id001 2021-01-01 08:03:00
#> 5 id001 2021-01-01 08:05:00
#> 6 id001 2021-01-01 08:06:00
#> 7 id001 2021-01-01 08:07:00
#> 8 id001 2021-01-01 08:08:00
#> 9 id001 2021-01-01 08:12:00
#> 10 id001 2021-01-01 08:13:00
#> 11 id001 2021-01-01 08:14:00
#> 12 id001 2021-01-01 08:15:00
#> 13 id001 2021-01-01 08:16:00
#> 14 id001 2021-01-01 08:17:00
#> 15 id001 2021-01-01 08:18:00
现在,我需要识别事件。这意味着,找到发生在 sequence 中的 time_stamps
(sequence = 1 分钟间隔)。例如,这将是我的预期输出:
#> # A tibble: 15 x 3
#> id time_stamp events
#> <chr> <dttm> <chr>
#> 1 id001 2021-01-01 08:00:00 event_1
#> 2 id001 2021-01-01 08:01:00 event_1
#> 3 id001 2021-01-01 08:02:00 event_1
#> 4 id001 2021-01-01 08:03:00 event_1
#> 5 id001 2021-01-01 08:05:00 event_2
#> 6 id001 2021-01-01 08:06:00 event_2
#> 7 id001 2021-01-01 08:07:00 event_2
#> 8 id001 2021-01-01 08:08:00 event_2
#> 9 id001 2021-01-01 08:12:00 event_3
#> 10 id001 2021-01-01 08:13:00 event_3
#> 11 id001 2021-01-01 08:14:00 event_3
#> 12 id001 2021-01-01 08:15:00 event_3
#> 13 id001 2021-01-01 08:16:00 event_3
#> 14 id001 2021-01-01 08:17:00 event_3
#> 15 id001 2021-01-01 08:18:00 event_3
请注意,从第 4
行到 5
有 2 分钟 的间隔 - 导致下一个事件开始。从第 8
行到 9
行相同:间隔 4 分钟,然后下一个事件开始。
PS:我需要它在 dbplyr
中完全工作,即:不使用 collect()
任何想法将不胜感激!
谢谢!
解决方法
不使用 collect
意味着我们仅限于大多数 dplyr 函数,因为这些函数定义了 SQL 翻译。
与@Sinh_Nguyen 非常相似,我建议如下:
output = mf %>%
group_by(id) %>%
arrange(time_stamp) %>%
mutate(prev_time_stamp = lag(time_stamp,1)) %>%
mutate(hours_diff = DATEPART('hour',time_stamp - prev_time_stamp),min_part_diff = DATEPART('minute',time_stamp - prev_time_stamp)) %>%
mutate(gap = hours_diff * 60 + min_part_diff) %>%
mutate(is_gap = ifelse(is.na(prev_time_stamp) | gap == 1,1)) %>%
mutate(event_index = cumsum(is_gap))
注意事项:
-
group_by
和arrange
在开始时发生一次,但由lag
和cumsum
函数隐式使用。 - 如果 dbplyr 没有定义翻译,那么它会按原样传递命令。大写
DATEPART
确保它不会被翻译,所以我们得到了 PostgreSQLDATEPART
函数。我通常使用SQL服务器,所以我关注these examples如何计算PostgreSQL中的差异。 - 最后两行的想法是在记录不是前一事件的延续时创建一个二元指标。将这些指标相加会增加每个新事件的事件计数器。
- 如果有错误,可以使用
show_query(output)
查看SQL翻译。查看/共享 SQL 翻译通常有助于解决问题。
这是使用逻辑 1 mins
差异均值 1 事件的代码。
mf %>%
collect() %>%
mutate(time_stamp = as_datetime(time_stamp)) %>%
mutate(diff_mins = difftime(time_stamp,lag(time_stamp,1),units = "mins")) %>%
mutate(event_count = if_else(diff_mins == 1 | is.na(diff_mins),1)) %>%
mutate(event_index = paste0("event_",cumsum(event_count) + 1))
输出:
# A tibble: 15 x 5
id time_stamp diff_mins event_count event_index
<chr> <dttm> <drtn> <dbl> <chr>
1 id001 2021-01-01 08:00:00 NA mins 0 event_1
2 id001 2021-01-01 08:01:00 1 mins 0 event_1
3 id001 2021-01-01 08:02:00 1 mins 0 event_1
4 id001 2021-01-01 08:03:00 1 mins 0 event_1
5 id001 2021-01-01 08:05:00 2 mins 1 event_2
6 id001 2021-01-01 08:06:00 1 mins 0 event_2
7 id001 2021-01-01 08:07:00 1 mins 0 event_2
8 id001 2021-01-01 08:08:00 1 mins 0 event_2
9 id001 2021-01-01 08:12:00 4 mins 1 event_3
10 id001 2021-01-01 08:13:00 1 mins 0 event_3
11 id001 2021-01-01 08:14:00 1 mins 0 event_3
12 id001 2021-01-01 08:15:00 1 mins 0 event_3
13 id001 2021-01-01 08:16:00 1 mins 0 event_3
14 id001 2021-01-01 08:17:00 1 mins 0 event_3
15 id001 2021-01-01 08:18:00 1 mins 0 event_3
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。