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

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)

代码说明
  1. 添加unit_seq:给每个Year内的Unit按Cumulated_Power顺序编号,便于后续匹配。
  2. 分组计算匹配位置:用findInterval替代which+min,快速定位每个缺失负荷需要覆盖的Unit数量,效率远超逐行循环。
  3. 连接获取Unit名称:通过Year和unit_seq的关联,拿到对应Unit的名称。
  4. 转宽表:用dcast将长表转为预期的宽表格式,不足的位置自动填充NA。

该方法利用data.table的向量化和分组特性,既解决了原代码的不等长比较错误,又大幅提升了大表处理效率。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 03:33:12