分组DT调用combn报错‘n < m’及修正时遇新问题
解决data.table中combn报错及do.call参数错误的问题
首先,咱们拆解下你遇到的两个问题,再给出针对性的解决方案:
问题1:combn(Materials, 2, simplify = FALSE) : n < m
这个错误的原因很明确:你的数据里存在部分Order.number对应的Materials只有1条记录(甚至为空),而combn(x,2)要求输入的向量长度至少为2,没法选出2个元素的组合时自然会报错。
问题2:Error in do.call(rbind, function(x) ...) : second argument must be a list
你尝试用函数判断材料长度,但do.call的第二个参数必须是可被rbind处理的列表/数据框,直接传入函数对象不符合参数要求,所以触发了这个错误。
正确的解决方案
我们可以在data.table的分组操作里,先判断当前订单的材料数量,只有数量≥2时才生成组合,否则返回空值跳过该组,同时优化组合生成逻辑:
library(data.table) # 初始化并排序data.table(你已完成的步骤) DT <- data.table(Order.number = X$Order.number, Materials = X$Materials) setorder(DT, Order.number, Materials) # 核心处理代码 ans <- DT[, { # 可选:对当前订单的材料去重,避免同一订单内重复材料生成无效组合 unique_mats <- unique(Materials) # 判断材料数量是否满足生成两两组合的要求 if (length(unique_mats) >= 2) { # 生成两两组合并转置为数据框(t()让组合直接变成两列) as.data.table(t(combn(unique_mats, 2))) } else { # 材料数量不足时返回NULL,该组不会被计入结果 NULL } }, by = Order.number][, .N, by = .(V1, V2)]
代码说明
- 分组内判断材料数量:通过
length(unique_mats) >=2筛选出能生成组合的订单,跳过材料数量不足的组,从根源避免combn的报错。 t(combn(...))的作用:默认combn返回按列排列的组合,转置后直接得到两列的V1和V2,不需要再用do.call(rbind,...)处理嵌套列表,简化了逻辑。- 去重操作:如果你的数据里存在同一订单重复记录相同材料的情况,
unique(Materials)可以避免生成(A,A)这类无效组合;如果不需要去重,直接去掉unique()即可。
内容的提问来源于stack exchange,提问作者M.A
相关产品推荐
相关产品推荐

