R data.table如何基于上下行土层数据计算平均值填充当前行
解决方案
直接用data.table内置的shift函数实现,不需要做复杂自连接,适配多地点、不同土层数量的场景,性能和简洁度都更好。
实现代码
library(data.table) # 示例数据 dt <- data.table(id = rep(c(1,2), 1, each = 3), depth = c(10, 20, 30, 10, 20, 30), val = c(12, 18, 11, 25, 27, 29), bot_l = c(20, 30, NA, 20, 30, NA), top_l = c(NA, 10, 20, NA, 10, 20)) # 第一步:确保数据按 地点id+深度 升序排列,这是取上下层的前提 setorder(dt, id, depth) # 第二步:按id分组,生成上一层、下一层的val值,直接计算均值 dt[, `:=`( # 上一层的值(lag:前一行),最表层为NA val_lag = shift(val, n = 1, type = "lag"), # 下一层的值(lead:后一行),最底层为NA val_lead = shift(val, n = 1, type = "lead") ), by = id][, # 对上下层值求平均,自动忽略NA mean_top_bot := rowMeans(.SD, na.rm = TRUE), .SDcols = c("val_lag", "val_lead") ] # 可选:删除不需要的中间列 dt[, `:=`(val_lag = NULL, val_lead = NULL)]
结果验证
运行后得到的mean_top_bot列完全符合预期:
- 最表层:只有下一层值,直接返回下一层val
- 最底层:只有上一层值,直接返回上一层val
- 中间层:返回上下两层val的平均值
基于已有top_l/bot_l字段的实现
如果你要沿用已经计算好的上下层深度字段,也可以用下面的方法:
dt[, mean_top_bot := rowMeans( data.table( top_val = dt[.BY, val[match(top_l, depth)]], bot_val = dt[.BY, val[match(bot_l, depth)]] ), na.rm = TRUE ), by = id]
内容的提问来源于stack exchange,提问作者Daniel
相关产品推荐
相关产品推荐

