R中不同大小data.table匹配报错求助:按小时匹配机组至满足功率条件
问题描述
我有两个大小不同的data.table:Tab_consolidated(3612行)和Tab_missing_load(24万+行),尝试用Stack Overflow上的解决方案代码匹配每个小时需要填补缺失负荷的Units时触发错误。
数据结构
Tab_consolidated结构示例:
> head(Tab_consolidated) Year Units Power Marginal_cost Cumulated_Power <dbl> <chr> <dbl> <dbl> <dbl> 1 2023 El_WK_Mol_B1 200 150 200 2 2023 El_WK_Mol_B2 150 200 350 3 2023 El_WK_Rab_B1 300 220 650 4 2024 El_WK_Mol_B2 150 200 200 5 2024 El_WK_Bag_B6 200 250 400 6 2024 El_WK_Bag_B7 330 270 730
Tab_missing_load结构示例:
> head(Tab_missing_load) Year Hour_day Hour_year Missing_load <dbl> <dbl> <dbl> <dbl> 1: 2023 1 1 442.017 2: 2023 2 2 401.548 3: 2023 3 3 375.848 4: 2023 4 4 319.509 5: 2023 5 5 318.953 6: 2023 6 6 141.473
原代码与错误
原解决方案代码:
library(data.table) f <- function(ml,y, cons) { cons[Year==y, .SD[1:min(which(Cumulated_Power>ml)), .(Year,Units)]] } setDT(Tab_missing_load) setDT(Tab_consolidated) dcast( Tab_missing_load[, f(Missing_load,Year,Tab_consolidated), .I][,id:=paste0(rowid(I), "_Unit")], Year+I~id, value.var="Units", )
运行后报错:
Error in .prepareFastSubset(isub = isub, x = x, enclos = parent.frame(), : RHS of == is length 245280 which is not 1 or nrow (3612). For robustness, no recycling is allowed (other than of length 1 RHS). Consider %in% instead.
预期输出
Year I 1_Unit 2_Unit 3_Unit <int> <int> <char> <char> <char> 1: 2023 1 El_WK_Mol_B1 El_WK_Mol_B2 El_WK_Rab_B1 2: 2023 2 El_WK_Mol_B1 El_WK_Mol_B2 El_WK_Rab_B1 3: 2023 3 El_WK_Mol_B1 El_WK_Mol_B2 El_WK_Rab_B1 4: 2023 4 El_WK_Mol_B1 El_WK_Mol_B2 <NA> 5: 2023 5 El_WK_Mol_B1 El_WK_Mol_B2 <NA> 6: 2023 6 El_WK_Mol_B1 <NA> <NA>
错误原因
原函数f中,cons[Year==y, ...]的y是Tab_missing_load的Year列(24万+长度),而Tab_consolidated仅3612行。data.table严格禁止不等长的==比较(仅允许RHS长度为1的情况),因此触发报错;同时逐行调用函数的方式效率极低,不适合大表处理。
解决方案
采用data.table的分组连接+滚动匹配实现高效处理,代码如下:
library(data.table) # 转为data.table格式 setDT(Tab_consolidated) setDT(Tab_missing_load) # 给每个Year内的Unit按顺序编号(按Cumulated_Power排序) Tab_consolidated[, unit_seq := rowid(Year)] # 按Year分组,计算每个Missing_load需要覆盖的Unit范围 match_result <- Tab_missing_load[, { # 取出当前Year对应的Consolidated数据 cons_year <- Tab_consolidated[Year == .BY$Year] # 快速定位每个Missing_load对应的Unit数量 pos <- findInterval(Missing_load, cons_year$Cumulated_Power) + 1L # 生成每行对应的unit_seq序列 .( I = .I, unit_seq = rep(seq_len(max(pos)), .N)[sequence(pos)] ) }, by = Year] # 连接获取对应的Unit名称 match_result <- match_result[Tab_consolidated, on = .(Year, unit_seq), Units := i.Units] # 转宽表得到预期格式 final_result <- dcast(match_result, Year + I ~ paste0(unit_seq, "_Unit"), value.var = "Units") # 查看结果 head(final_result)
代码说明
- 添加
unit_seq:给每个Year内的Unit按Cumulated_Power顺序编号,便于后续匹配。 - 分组计算匹配位置:用
findInterval替代which+min,快速定位每个缺失负荷需要覆盖的Unit数量,效率远超逐行循环。 - 连接获取Unit名称:通过
Year和unit_seq的关联,拿到对应Unit的名称。 - 转宽表:用
dcast将长表转为预期的宽表格式,不足的位置自动填充NA。
该方法利用data.table的向量化和分组特性,既解决了原代码的不等长比较错误,又大幅提升了大表处理效率。
内容的提问来源于stack exchange,提问作者bLanton70
相关产品推荐
相关产品推荐

