测定站的记录几乎不可能每天都有:猪某天没进站、耳标没读到、设备故障,或者进站晚、出栏早。tidypptsda 不绕开缺失,而是先把计算区间(默认 30–120 kg)内的每一天都补上体重和采食量,再计算日增重(ADG)、日采食量(ADFI)和料肉比(FCR)。补的方法取决于缺失的位置:在两个有记录的日子之间,还是在首个记录之前、末个记录之后。
本文用一头示例猪逐步演示每一种填充,说明它由哪个参数控制、结果里用什么标签标出。
下面这头猪来自示例数据
nedap。为了让每种情况都出现,人为删掉了它的一部分访问:区间开头
12 天(晚进站)、中间 2 天(短缺口)、中间 6 天(长缺口)和结尾 8
天(早出栏)。图中所有的点和线都是包实际算出来的结果。点 ▶
播放 自动演示,也可以用 上一步 / 下一步
逐步查看。
| 缺失位置 | 体重:方法 | 体重:参数 | source |
采食:方法 | 采食:参数 | state |
|---|---|---|---|---|---|---|
| 有记录的日子 | 当天有效记录的中位数 |
weight_range、adapt_days、weight_track、weight_outlier
|
observed |
记录值;有错误访问时混合模型校正 |
dfi_correct、dfi_range、dfi_quantile
|
org / corr
|
| 两个有记录的日子之间,≤ 3 天 | 线性插值 | — | interpolated |
稳健 LOESS |
long_gap_days、loess_span
|
iii |
| 两个有记录的日子之间,> 3 天 | 线性插值 | — | interpolated |
群体曲线 × 个体比例 | impute_method = "loess_pop" |
iii |
| 首个记录之前(晚进站) | 切线外推 |
curve_extrap = "start"、max_extrap_days
|
curve |
群体曲线 × 个体比例 | impute_method = "loess_pop" |
elrp |
| 末个记录之后(早出栏) | 生长曲线 |
curve_model、max_extrap_days
|
curve |
这头猪自己的”日采食 ~ 体重”回归 | impute_method |
elrp |
| 外推后仍到不了 30 或 120 kg | 不填,只算覆盖到的部分 | max_extrap_days |
— | 只在覆盖到的部分计算 | — | — |
几点说明:
adg$daily$weight_filled)。所以体重填充的方法也会影响采食的填充。前后两个有记录日子的日体重之间连成直线。中间缺失时,前后两天的实测最能说明这头猪当时的状态;在示例数据上,人为隐藏中间的日子再填回,线性插值的日体重误差约 0.8 kg,用生长曲线约 1.1–1.6 kg(见《方法验证》)。
curve_extrap |
首个记录之前 | 末个记录之后 |
|---|---|---|
"start"(默认) |
切线:首 14 天记录的稳健斜率 | 生长曲线 |
"tangent" |
切线 | 切线:末 14 天记录的稳健斜率 |
"curve" |
生长曲线 | 生长曲线 |
切线的斜率限制在 0.2–1.5 kg/d。二次、三次曲线往记录外推几周时容易弯折;在 457 头 NEDAP 猪的无泄露检验中,开头缺 20 天时,开头用切线使 ADG 误差从 81 降到 66 g/d、FCR 排名相关从 0.82 升到 0.86。末端用切线虽然 ADG 更准,但采食是按体重外推的,FCR 排名反而变差,所以默认只在开头用切线。
日采食 = r × f(体重)
f:全部猪区间内有记录日子的二次回归
日采食 ~ 体重 + 体重²;有 breed 列时,不少于
10
头的品种各拟合一条,其余的猪用全群曲线;超出拟合时的体重范围,取端点的值。曲线系数在
adfi$pop_curve 中。r:这头猪有记录日子的采食之和 ÷ 同样日子上
f 之和,再按记录天数 n 向 1 收缩(权重
n / (n + 10))。r
保留这头猪自己的水平。
# 两端都用生长曲线外推(1.4.0 之前的做法)
qc_config(curve_extrap = "curve")
# 长缺口和两端都用这头猪自己的回归(1.3.0 之前的做法)
qc_config(impute_method = "loess_lm")
# 晚进站多、记录短的批次:直线生长曲线
qc_config(curve_model = "poly1", stage_range = c(60, 120))换方法之前,先用 validate_truncation()
在自己的数据上比较:它删掉一部分猪若干天的全部访问后重跑整个流程,与全部数据的结果比较,不会有被隐藏的信息泄露回来(见《方法验证》)。
a$per_pig[responder == pig, .(adg, adg_type, n_observed_days, n_interpolated_days,
n_curve_days, extrap_days_start, extrap_days_end)]
#> adg adg_type n_observed_days n_interpolated_days n_curve_days
#> <num> <char> <int> <int> <int>
#> 1: 1207.561 extrapolated 41 8 26
#> extrap_days_start extrap_days_end
#> <num> <num>
#> 1: 14.75088 10.97878
f$per_pig[responder == pig, .(adfi, coverage, n_observed, n_interpolated, n_extrapolated,
n_extrap_start, n_extrap_end)]
#> adfi coverage n_observed n_interpolated n_extrapolated n_extrap_start
#> <num> <num> <int> <int> <int> <int>
#> 1: 2750.359 0.64 48 8 19 8
#> n_extrap_end
#> <int>
#> 1: 11a$daily$source 和 f$daily$state
标出每一天的来源;plot_adg() 和 plot_adfi()
用不同的颜色画出来。calc_fcr()
会把两端连续填充超过
max_edge_extrap_days(15)天、或采食实测比例低于
min_coverage(0.7)的猪标为
low_confidence。