You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在R中完成开关通断状态持续时长的后续计算?

问题描述

现有如下R语言数据框data:

data<-data.frame(ymdhms=c(20230301000000,20230301000010,20230301000020,20230301000030,20230301000040,
                          20230301000050,20230301000100,20230301000110,20230301000120,20230301000130,
                          20230301000140,20230301000150,20230301000200,20230301000210,20230301000220),
                 switch=c(40,41,42,43,0,0,0,51,52,53,54,0,0,48,47))

其中:

  • ymdhms为年月日时分秒的拼接数值,例如20230301000000对应2023年3月1日00:00:00;
  • switch值>0代表开关开启(on),=0代表关闭(off),所有值非负;
  • 每行数据的时间间隔固定为10秒。

需要统计开关各段状态的持续时长,预期输出数据框如下:

on_off<-data.frame(on=c(30,30,10),off=c(20,10,NA))

已完成辅助列的添加:

data$dt <- as.POSIXct(strptime(formatC(data$ymdhms, format='f'), format='%Y%m%d%H%M%S'))
data$switchStatus_A <- ifelse(data$switch > 0, 1, 0) # 1标记开启,0标记关闭
解决方案

通过状态分组、时长计算、结果对齐三步即可实现目标:

1. 为连续相同状态分配分组ID

把连续的开启/关闭状态划分为独立分组,提供两种实现方式:

# 方式1:使用data.table包的rleid函数(简洁高效)
library(data.table)
data$group_id <- rleid(data$switchStatus_A)

# 方式2:基础R实现,无需额外包
data$group_id <- cumsum(c(1, diff(data$switchStatus_A) != 0))

2. 计算各状态段的持续时长

结合时间列dt计算每个分组的实际持续时长,同时处理最后一个无后续状态的段:

library(dplyr)

# 添加下一行的时间列,用于计算状态结束时间
data$next_dt <- lead(data$dt)

# 按分组统计时长
duration_summary <- data %>%
  group_by(group_id, switchStatus_A) %>%
  summarise(
    # 状态段的结束时间:有后续状态则取下一段的开始时间,否则取当前段最后一行的时间
    end_time = ifelse(!is.na(last(next_dt)), last(next_dt), last(dt)),
    start_time = first(dt),
    .groups = "drop"
  ) %>%
  mutate(
    duration = as.numeric(difftime(end_time, start_time, units = "secs")),
    # 最后一个状态段需额外加10秒(每行间隔10秒,最后一行的状态持续到下一个10秒节点)
    duration = ifelse(is.na(last(next_dt)) & switchStatus_A == 1, duration + 10, duration),
    status = ifelse(switchStatus_A == 1, "on", "off")
  ) %>%
  select(status, duration)

3. 对齐on/off时长,生成目标数据框

将开启和关闭时长按交替顺序配对,最后一个状态若无对应状态则补NA:

# 分离on和off的时长列表
on_list <- duration_summary$duration[duration_summary$status == "on"]
off_list <- duration_summary$duration[duration_summary$status == "off"]

# 对齐两个列表的长度,不足的位置补NA
max_length <- max(length(on_list), length(off_list))
on_list <- c(on_list, rep(NA, max_length - length(on_list)))
off_list <- c(off_list, rep(NA, max_length - length(off_list)))

# 创建目标数据框
on_off <- data.frame(on = on_list, off = off_list)

运行后即可得到与预期一致的结果:

> on_off
   on off
1  30  20
2  30  10
3  10  NA

内容的提问来源于stack exchange,提问作者Lee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 00:47:56