r - 根据班级保持时间顺序折叠常规时间段数据
问题描述
这个问题与我之前在以下链接中的帖子密切相关: 将时间段扩展到定期出现的时间戳
本质上,这是该问题的相反步骤。
我现在有一个定期间隔的数据集(1 分钟周期),我需要折叠这些周期,以便每一行代表一个类保持不变的时间段,如下所示:
示例输入数据框是:
df_in <- tibble(st =seq(ymd_hms("2016-01-01 00:35:00"),
ymd_hms("2016-01-01 00:58:00")-60,60),
en = st+59)
df_in$cl <- c("a",rep("c",3),rep("a",6),rep("c",9),rep("a",1),"c",rep("b",2))
我设法通过如下代码所示的循环来完成此操作,但这非常低效且速度慢(我的数据源在数百万行中)。我确信有一种通过 dplyr 执行此操作的 Verctorized 方式,我希望有人能指出我正确的方向:
df_in$flag <- 1
df_in %>%
mutate(flag = ifelse(lag(cl)==cl,0,1)) -> df_in
df_in$flag[1] <- 1
df_in$flag2 <- 0
df_in$flag2[1] <- 1
for (i in 2:nrow(df_in)) {
if (df_in$flag[i] == 0) {
df_in$flag2[i] = df_in$flag2[i-1]
} else {
df_in$flag2[i] = df_in$flag2[i-1] + 1
}
}
df_in %>%
group_by(flag2) %>%
summarise(st = min(st),
en = max(en),
cl = unique(cl)) %>%
View()
再次提前感谢...
解决方案
这是使用的一个选项data.table
library(data.table)
setDT(df_in)[, .(st = min(st), en = max(en)), by = .(cl, idx = rleid(cl))]
# cl idx st en
#1: a 1 2016-01-01 00:35:00 2016-01-01 00:35:59
#2: c 2 2016-01-01 00:36:00 2016-01-01 00:38:59
#3: a 3 2016-01-01 00:39:00 2016-01-01 00:44:59
#4: c 4 2016-01-01 00:45:00 2016-01-01 00:53:59
#5: a 5 2016-01-01 00:54:00 2016-01-01 00:54:59
#6: c 6 2016-01-01 00:55:00 2016-01-01 00:55:59
#7: b 7 2016-01-01 00:56:00 2016-01-01 00:57:59
我们设置st
等于min(st)
和en
等于max(en)
bycl
和idx = rleid(cl)
。rleid
创建一个“运行长度类型 id 列”。
和dplyr
你一起做
library(dplyr)
df_in %>%
mutate(idx = data.table::rleid(cl)) %>%
group_by(cl, idx) %>%
summarise(st = min(st),
en = max(en)) %>%
arrange(idx) %>%
select(-idx)
推荐阅读
- c++ - 找不到无效 free() / delete / delete[] / realloc() 的原因
- c - 如果我正在构建一个操作系统,那么使用我的主机操作系统的 gcc 编译器是否有意义?
- c++ - CUDA 将错误显示为矩阵的“无效参数” - 乘以 N 次
- rust - 检查是否在 Cargo 构建脚本中构建测试
- acumatica - 移动从商机创建销售报价
- graphql - 在 graphql-java-tools 中禁用 GraphQL Introspection
- java - 从 go 或 java 程序调用 c 有什么危险?
- advanced-custom-fields - acf/save_post 直到手动更新才会触发
- r - 在 R 中按分隔符分隔数据:如何指定分隔字符的分隔符(例如 5 个系列中的第 4 个)?
- python - 如何将其转换为新数据框中的列