不使用split函数在R中划分30分钟时间间隔的数据表
问题描述
我有一份时长21天、每10秒采集一次的数据表,结构如下:
TimeStamp ActivePower CurrentL1 GeneratorRPM RotorRPM WindSpeed 2017-03-05 00:00:10 2183.650 1201.0 1673.90 NA 10.60 2017-03-05 00:00:20 2216.200 1224.0 1679.70 NA 11.00 2017-03-05 00:00:30 2176.500 1203.5 NA 16.05 11.90 --- 2017-03-25 23:59:40 2024.20 1150.0 1687.00 16.15 10.35 2017-03-25 23:59:50 1959.05 1106.0 1661.15 15.90 8.65 2017-03-26 00:00:00 1820.55 1038.0 1665.70 15.80 9.20
需要将其划分为30分钟的时间块,同事告知因数据可能存在缺失时间戳,不应使用split函数,需手动生成30分钟间隔。目前已完成以下代码:
library(data.table) library(dplyr) library(tidyr) datei <- file.choose() data_csv <- fread(datei) datatable1 <- as.data.table(data_csv) datatable1 <- datatable1[turbine=="UTHA02",] datatable1[, TimeStamp:=as.POSIXct(get("_time"), tz="UTC")] setkey(datatable1, TimeStamp) startdate <- datatable1[1,TimeStamp] enddate <- datatable1[nrow(datatable1), TimeStamp] durationForInterval <- 30*60 #in seconds curr <- startdate datatable1[TimeStamp >= curr & TimeStamp < curr + durationForInterval]
上述代码仅能获取第一个30分钟间隔的数据,如下所示:
time ActivePower CurrentL1 GeneratorRPM RotorRPM WindSpeed 1: 2017-03-05 00:00:10 2183.65 1201.0 1673.90 NA 10.60 2: 2017-03-05 00:00:20 2216.20 1224.0 1679.70 NA 11.00 3: 2017-03-05 00:00:30 2176.50 1203.5 NA 16.05 11.90 4: 2017-03-05 00:00:40 2267.95 1256.5 1685.85 NA 10.60 5: 2017-03-05 00:00:50 2533.15 1408.0 1693.30 16.20 12.40 --- 176: 2017-03-05 00:29:20 2750.35 1531.0 1694.40 16.20 11.45 177: 2017-03-05 00:29:30 2930.40 1630.5 1668.25 NA 12.65 178: 2017-03-05 00:29:40 2459.55 1367.0 1680.25 15.90 12.15 179: 2017-03-05 00:29:50 2713.80 1508.5 1681.15 16.20 12.25 180: 2017-03-05 00:30:00 2395.20 1333.0 1667.75 16.00 11.75
不知道如何处理剩余的时间间隔,恳请提供解决方案或指出疏漏之处!
解决方案
核心思路
手动生成覆盖数据全时间范围的30分钟间隔序列,通过data.table的非等连接将原数据映射到对应时间块,或直接给原数据添加时间块标签,避免循环遍历的低效问题,同时适配缺失时间戳的场景。
完整代码(基于data.table)
library(data.table) # 读取并过滤数据 datei <- file.choose() datatable1 <- fread(datei) datatable1 <- datatable1[turbine == "UTHA02",] # 转换时间戳(直接引用列名,简化逻辑) datatable1[, TimeStamp := as.POSIXct(`_time`, tz = "UTC")] setkey(datatable1, TimeStamp) # 定义30分钟间隔参数 interval_sec <- 30 * 60 startdate <- datatable1[1, TimeStamp] enddate <- datatable1[.N, TimeStamp] # 生成所有30分钟间隔的起止时间序列 # 可选:将起始时间向上取整到最近的30分钟整点,保证块对齐 start_rounded <- as.POSIXct(floor(as.numeric(startdate)/interval_sec)*interval_sec, origin = "1970-01-01", tz = "UTC") time_intervals <- seq(start_rounded, enddate + interval_sec, by = interval_sec) # 构建时间块映射表 interval_table <- data.table( block_start = time_intervals[-length(time_intervals)], block_end = time_intervals[-1], block_id = seq_along(time_intervals[-length(time_intervals)]) ) # 非等连接匹配数据到对应时间块 datatable_with_blocks <- datatable1[interval_table, on = .(TimeStamp >= block_start, TimeStamp < block_end), nomatch = 0] # 示例:按时间块计算均值 block_summary <- datatable_with_blocks[, .( avg_ActivePower = mean(ActivePower, na.rm = TRUE), avg_CurrentL1 = mean(CurrentL1, na.rm = TRUE), avg_WindSpeed = mean(WindSpeed, na.rm = TRUE) ), by = block_id] # 若需按块拆分数据为列表 block_list <- split(datatable_with_blocks, by = "block_id")
关键说明
- 时间序列完整性:生成
time_intervals时添加enddate + interval_sec,确保所有末尾数据点都能被覆盖,即使enddate不在30分钟整点上。 - 非等连接优势:比循环遍历效率高数十倍,适合处理大样本量(21天10秒间隔约18万行数据),同时自动跳过无数据的时间块。
- 简化替代方案:若不需要单独的间隔表,可直接给原数据添加时间块标签:
datatable1[, block_id := floor(as.numeric(TimeStamp - start_rounded)/interval_sec) + 1] # 后续直接按block_id分组处理即可
内容的提问来源于stack exchange,提问作者NoName
相关产品推荐
相关产品推荐

