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

如何在R中按Cost比例拆分数据集并保证ObjectID唯一分组

解决方案:按ObjectID分组并保持Cost比例的数据集拆分

要实现每个ObjectID仅属于训练/测试组一组,同时保持Cost的整体比例,你需要先按ObjectID聚合总Cost,再基于这个聚合后的总Cost进行分层抽样,最后映射回原始数据集。以下是具体步骤和R代码示例:

步骤1:准备数据并按ObjectID聚合总Cost

首先我们需要计算每个ObjectID的总Cost,这样就能基于每个ID对整体Cost的贡献来抽样,确保最终拆分的Cost比例符合要求:

# 加载必要的包
library(dplyr)
library(caret)

# 示例数据(替换成你的实际数据集即可)
data <- tibble(
  ObjectID = c(12345,12345,12345,12345,11111,11111,22222,22222,22222,33333,33333,44444,44444,44444,44444,55555,55555,55555),
  Cost = c(1624,1175,1049,1733,1945,1989,1448,1815,1244,1355,1134,1478,1082,1147,1290,1383,1378,1288),
  Type = c(rep("Test",4), rep("Train",2), rep("Test",3), rep("Train",2), rep("Train",4), rep("Train",3))
)

# 按ObjectID聚合,计算每个ID的总Cost
id_cost_summary <- data %>%
  group_by(ObjectID) %>%
  summarise(TotalCost = sum(Cost), .groups = "drop")

步骤2:基于总Cost进行分层抽样,确保每个ID仅在一组

这里用caret包的createDataPartition函数,它会根据目标变量(这里是TotalCost)的分布来抽样,保证训练集和测试集的Cost比例接近你设定的拆分比例:

# 设置拆分比例(70%训练,30%测试)
split_ratio <- 0.7

# 基于每个ID的TotalCost创建拆分索引,维持比例
train_id_indices <- createDataPartition(id_cost_summary$TotalCost, p = split_ratio, list = FALSE)

# 提取训练组和测试组的ObjectID
train_ids <- id_cost_summary$ObjectID[train_id_indices]
test_ids <- id_cost_summary$ObjectID[-train_id_indices]

步骤3:将原始数据映射到训练/测试组

最后把原始数据中的每条记录根据ObjectID分配到对应的组:

# 给原始数据添加分组标签
data_split <- data %>%
  mutate(Group = ifelse(ObjectID %in% train_ids, "Train", "Test"))

# 验证结果:检查训练组的总Cost占比
total_cost <- sum(data$Cost)
train_total_cost <- sum(data_split %>% filter(Group == "Train") %>% pull(Cost))
cat("训练组Cost占比:", round(train_total_cost / total_cost, 2), "\n")

关键说明

  • 这种方法彻底避免了同一个ObjectID的记录被拆分到两组的情况,完全符合你的需求。
  • 通过基于每个ID的总Cost抽样,能确保训练集和测试集的整体Cost比例尽可能接近设定值。
  • 如果需要更精确的Cost比例控制,也可以用sample函数结合prob = id_cost_summary$TotalCost参数做加权抽样,但createDataPartition已经能覆盖大多数场景的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 17:47:42