如何在data.table中按year、field分组,去除两列顺序互换的重复行
去除data.table中肥料名称顺序互换的重复行
Stack Overflow上已有类似问题,但均不适用于我当前的data.table数据格式,因此发布此问题。
我的data.table数据如下:
year field fert_name.x yield.x fert_name.y yield.y 1: 2017 field1 fertA 7.875775 fertB 14.404673 2: 2017 field1 fertA 7.875775 fertC 10.514350 3: 2017 field1 fertB 14.404673 fertA 7.875775 4: 2017 field1 fertB 14.404673 fertC 10.514350 5: 2017 field1 fertC 10.514350 fertA 7.875775 6: 2017 field1 fertC 10.514350 fertB 14.404673 7: 2017 field2 fertA 9.089769 fertB 10.281055 8: 2017 field2 fertA 9.089769 fertC 14.568333 9: 2017 field2 fertB 10.281055 fertA 9.089769 10: 2017 field2 fertB 10.281055 fertC 14.568333 11: 2017 field2 fertC 14.568333 fertA 9.089769 12: 2017 field2 fertC 14.568333 fertB 10.281055 13: 2018 field1 fertA 12.883051 fertB 5.455565 14: 2018 field1 fertA 12.883051 fertC 9.566147 15: 2018 field1 fertB 5.455565 fertA 12.883051 16: 2018 field1 fertB 5.455565 fertC 9.566147 17: 2018 field1 fertC 9.566147 fertA 12.883051 18: 2018 field1 fertC 9.566147 fertB 5.455565 19: 2018 field2 fertA 13.830174 fertB 13.924190 20: 2018 field2 fertA 13.830174 fertC 9.533342 21: 2018 field2 fertB 13.924190 fertA 13.830174 22: 2018 field2 fertB 13.924190 fertC 9.533342 23: 2018 field2 fertC 9.533342 fertA 13.830174 24: 2018 field2 fertC 9.533342 fertB 13.924190
我需要按year和field分组,去除所有fert_name.x与fert_name.y顺序互换的重复行——例如行1与行3(fertA/fertB和fertB/fertA)、行2与行5(fertA/fertC和fertC/fertA)这类配对只保留一行。
数据集复现代码
library(data.table) # 创建模拟数据 dat <- data.table(expand.grid(year=2017:2018, field=c("field1","field2"), fert_name=c("fertA","fertB","fertC"), stringsAsFactors=F)) set.seed(123); yld <- runif(12, min=5, max=15) dat$yield <- yld (dat.m <- merge(dat, dat, by=c("year","field"), allow.cartesian=T)[fert_name.x != fert_name.y])
最优实现方案
利用data.table的分组筛选功能,直接在每个year+field组内保留fert_name.x字典序小于fert_name.y的行,这样每个肥料配对只会保留一行:
# 保留每个配对的唯一行 dat.unique <- dat.m[ , .SD[fert_name.x < fert_name.y], by = .(year, field)]
方案说明
- 字符串的字典序比较(
fertA < fertB < fertC)可以确保每个肥料配对(如fertA&fertB)只会留下fert_name.x在前的那一行,自动剔除反向的重复行。 - 这种方式无需额外生成辅助列,直接在分组内筛选,效率很高,适合大规模数据集。
- 处理后的结果会从24行缩减为12行(每个分组3个肥料,共C(3,2)=3个唯一配对,2年×2地块×3=12行)。
备选方案(生成唯一配对标识)
如果需要更灵活的配对判断,可以生成一个包含排序后肥料名称的辅助列,再通过去重实现:
# 生成排序后的配对标识 dat.m[, fert_pair := paste(pmin(fert_name.x, fert_name.y), pmax(fert_name.x, fert_name.y), sep = "-"), by = .(year, field)] # 去重 dat.unique <- dat.m[!duplicated(fert_pair)] # 可选:删除辅助列 dat.unique[, fert_pair := NULL]
内容的提问来源于stack exchange,提问作者thiagoveloso
相关产品推荐
相关产品推荐

