使用R语言计算开关启停时段的NH4统计值及时长
正确计算开关状态时段统计的R语言代码
原始数据集
data <- data.frame( time = c(20230301000000,20230301000010,20230301000020,20230301000030,20230301000040, 20230301000050,20230301000100,20230301000110,20230301000120,20230301000130, 20230301000140,20230301000150,20230301000200,20230301000210,20230301000220, 20230301000230,20230301000240,20230301000250,20230301000300), switch = c(40,41,42,43,0,0,0,51,52,53,0,0,0,55,56,57,52,0,0), NH4 = c(2,2,3,3,3,5,4,9,9,9,10,11,12,4,4,5,5,7,8) )
需求说明
switch > 0表示开关开启,switch = 0表示开关关闭- 需计算每次开关状态的持续时长(单位:秒)
- 每个状态时段内计算
NH4的最小值、平均值、最大值:- 开启状态对应
on_NH4_min、on_NH4_avg、on_NH4_max - 关闭状态对应
off_NH4_min、off_NH4_avg、off_NH4_max
- 开启状态对应
期望输出
summary_data <- data.frame( on_NH4_min = c(2,9,4), on_NH4_avg = c(2.5,9,4.5), on_NH4_max = c(3,9,5), off_NH4_min = c(3,10,7), off_NH4_avg = c(4,11,7.5), off_NH4_max = c(5,12,8), on_time = c(30,20,30), off_time = c(30,30,20) )
原代码问题说明
之前的代码错误地将所有开启/关闭状态合并统计,没有按连续的状态区间分组,导致无法得到每个时段的单独统计结果。
正确代码实现
library(dplyr) library(tidyr) # 1. 标记开关状态,生成连续状态区间的分组ID data_processed <- data %>% mutate( switch_state = ifelse(switch > 0, "on", "off"), # 当状态变化时,分组ID递增 group_id = cumsum(switch_state != lag(switch_state, default = first(switch_state))) ) # 2. 按分组ID和状态分组,计算每个时段的统计量和时长 interval_stats <- data_processed %>% group_by(group_id, switch_state) %>% summarise( NH4_min = min(NH4), NH4_avg = mean(NH4), NH4_max = max(NH4), # 计算时长:将time转为时间格式后计算差值,单位秒 duration = as.numeric(difftime( as.POSIXct(last(time), format = "%Y%m%d%H%M%S"), as.POSIXct(first(time), format = "%Y%m%d%H%M%S"), units = "secs" )) + 10 # 补全最后一个数据点到时段结束的10秒间隔 ) %>% ungroup() # 3. 将on/off状态的统计量宽格式展开,并按顺序对齐 summary_data <- interval_stats %>% pivot_wider( names_from = switch_state, values_from = c(NH4_min, NH4_avg, NH4_max, duration), names_glue = "{switch_state}_{.value}" ) %>% # 调整列名匹配期望输出 select( on_NH4_min, on_NH4_avg, on_NH4_max, off_NH4_min, off_NH4_avg, off_NH4_max, on_time = on_duration, off_time = off_duration ) # 查看结果 print(summary_data)
代码说明
- 状态分组:通过
cumsum(switch_state != lag(switch_state))生成连续状态的分组ID,确保每个连续的on/off时段被单独分组。 - 时长计算:将
time列转为POSIX时间格式,计算时段首尾的时间差,再加上最后一个数据点到时段结束的10秒(数据每10秒采集一次)。 - 宽格式转换:使用
pivot_wider将on/off状态的统计量展开为期望的列名格式,确保每个时段的on和off统计量对应成行。
内容的提问来源于stack exchange,提问作者Lee
相关产品推荐
相关产品推荐

