R语言计算灌溉滴头首次持续堵塞时间(含异常标记)
解决方案:计算滴头首次持续堵塞时间并标记异常波动滴头
核心需求梳理
- 按每个滴头(
id列)分组,找到首次切换为堵塞(Working=0)且后续状态持续为0的时间点 - 若滴头出现「堵塞后恢复正常」的波动(即0之后再次出现1),需标记该滴头,并忽略这次堵塞,继续找后续的持续堵塞点
- 计算从实验初始时间到该堵塞时间的天数
代码实现(基于tidyverse工具链)
首先加载所需包:
library(dplyr) library(lubridate)
然后处理数据,直接用你提供的示例数据:
# 赋值示例数据 df <- structure(list(Date = structure(c(1660089600, 1660089600, 1660521600, 1660521600, 1660780800, 1660780800, 1661385600, 1661385600, 1661904000, 1661904000, 1662249600, 1662249600, 1662336000, 1662336000), tzone = "UTC", class = c("POSIXct", "POSIXt")), Lateral = structure(c(2L, 4L, 2L, 4L, 2L, 4L, 2L, 4L, 2L, 4L, 2L, 4L, 2L, 4L), levels = c("1", "2", "3", "4"), class = "factor"), Position = structure(c(1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L), levels = c("1", "2", "3", "4", "5", "6"), class = "factor"), `Distance (m)` = c(0.9, 1.8, 0.9, 1.8, 0.9, 1.8, 0.9, 1.8, 0.9, 1.8, 0.9, 1.8, 0.9, 1.8), Type = structure(c(2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L), levels = c("Copper", "Normal"), class = "factor"), Working = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 0L, 1L, 1L, 0L, 0L, 0L, 0L), id = c(6L, 18L, 6L, 18L, 6L, 18L, 6L, 18L, 6L, 18L, 6L, 18L, 6L, 18L)), row.names = c(NA, -14L), class = c("tbl_df", "tbl", "data.frame")) # 核心处理逻辑 result <- df %>% # 按滴头id分组 group_by(id) %>% # 确保每个滴头的记录按时间升序排列(避免时间顺序混乱) arrange(Date, .by_group = TRUE) %>% # 计算关键标记字段 mutate( # 标记是否出现堵塞后恢复的波动 has_fluctuation = any(Working == 1 & lag(cumsum(Working == 0) > 0, default = FALSE)), # 判断从当前行到最后一行是否全为堵塞状态 all_after_blocked = cumall(Working == 0) %>% rev() %>% cumall() %>% rev(), # 标记当前行是否是首次持续堵塞的时间点 is_permanent_block = Working == 0 & all_after_blocked & !lag(all_after_blocked, default = FALSE) ) %>% # 汇总每个滴头的关键信息 summarise( initial_date = first(Date), permanent_block_date = first(Date[is_permanent_block]), days_to_block = as.integer(difftime(permanent_block_date, initial_date, units = "days")), has_fluctuation = first(has_fluctuation), # 保留滴头的属性信息 Type = first(Type), Lateral = first(Lateral), Position = first(Position), `Distance (m)` = first(`Distance (m)`), .groups = "drop" ) # 查看结果 print(result)
代码关键步骤解释
- 分组排序:按
id分组后强制按时间排序,是后续时间序列计算的基础 - 波动判断:
has_fluctuation通过检测「已经出现过堵塞但之后又恢复正常」的记录,标记异常滴头 - 持续堵塞判定:
all_after_blocked通过反向累积判断,锁定从当前行开始后续全为堵塞的区间;is_permanent_block进一步筛选出这个区间的第一个时间点 - 结果汇总:提取每个滴头的初始时间、首次持续堵塞时间,计算天数差,并保留滴头的类型、位置等属性
示例数据运行结果
# A tibble: 2 × 9 id initial_date permanent_block_date days_to_block has_fluctuation Type Lateral Position `Distance (m)` <int> <dttm> <dttm> <int> <lgl> <fct> <fct> <fct> <dbl> 1 6 2022-08-09 00:00:00 2022-08-30 00:00:00 21 FALSE Normal 2 1 0.9 2 18 2022-08-09 00:00:00 2022-08-23 00:00:00 14 FALSE Copper 4 2 1.8
(示例数据中无堵塞后恢复的情况,若实际数据存在这类情况,has_fluctuation会显示TRUE)
内容的提问来源于stack exchange,提问作者sdabach
相关产品推荐
相关产品推荐

