R语言特殊合并需求求助:按Frequency分配Assessment至data.table
解决方法
基于data.table的高效语法可以快速实现需求,核心思路是先计算每个ID对应的dt1数据提取范围,再批量提取并拼接字符串:
完整代码
library(data.table) # 初始化数据(修正类型问题,避免cbind导致的字符转换) dt1 <- data.table(Assessment = c("perfect", "perfect", "okay", "unsufficient", "good", "good", "okay", "perfect")) dt2 <- data.table(ID = 1:6, Frequency = c(1,3,1,1,1,1)) # 计算每个ID对应的dt1行索引范围 dt2[, `:=`( start = shift(cumsum(Frequency), fill = 0) + 1, end = cumsum(Frequency) )] # 提取并拼接Assessment dt2[, Assessment := mapply(function(s, e) paste0(dt1$Assessment[s:e], collapse = ";"), start, end)] # 移除临时索引列(可选) dt2[, c("start", "end") := NULL] # 查看结果 dt2
代码说明
- 修正数据类型:原代码中用
cbind创建dt2会导致数值变为字符类型,直接指定列初始化更规范。 - 计算索引范围:
cumsum(Frequency):计算累计提取数量,得到每个ID对应的dt1结束行号shift(cumsum(Frequency), fill = 0) + 1:通过偏移累计和得到每个ID对应的dt1起始行号
- 批量提取拼接:用
mapply遍历每个索引范围,从dt1中提取对应行的Assessment,并用paste0(..., collapse=";")拼接成字符串。 - 清理临时列:可选移除用于计算的
start和end列,得到最终结果。
验证结果
运行代码后得到的dt2与期望结果完全一致:
ID Frequency Assessment 1: 1 1 perfect 2: 2 3 perfect;okay;unsufficient 3: 3 1 good 4: 4 1 good 5: 5 1 okay 6: 6 1 perfect
内容的提问来源于stack exchange,提问作者derhard
相关产品推荐
相关产品推荐

