tidypptsda 要解决的问题很具体:把测定站导出的一次次访问记录,变成每头猪可信、可比的日增重(ADG)、日采食量(ADFI)和料肉比(FCR)。本文说明这个包为什么这样设计:每一步背后的考虑、做过的取舍,以及刻意没有做的事。具体方法见《计算方法说明》,参数见《质控参数详解》。

1. 从测定站的实际情况出发

测定站的数据有它自己的”脾气”,方法要顺着它来设计,而不是套用通用的统计规则。

  • 称重只在猪四条腿都站上秤时才记录,所以读数偏轻的情况很少;
  • 偏重的读数很常见:进站初期猪小,测定站的挡板空隙即使调到最小,也能挤进去好几头小猪,读数是几头猪的体重之和或其中一部分;
  • 测定后期猪大了,秤上只容得下一头,读数最可靠;
  • 所以生产上要求猪至少 15 kg 进站,并留一周的适应期,这样之后计算 30 kg 以上的日增重才准。

这几条直接决定了体重清洗的顺序:先去掉 15–150 kg 以外的读数和 7 天适应期,再从最可靠的测定末期往前逐日追踪,只保留与推算体重衔接的读数,最后才用二次稳健回归和 LOESS 去掉零散的异常值。通用的异常值方法把整条曲线当作参照,进站初期一半读数都偏重时,曲线本身就被拉高了,所以不能只靠它们。

追踪剔除的记录很多(超过 40%)时,问题通常不在猪,而在秤:比如一头猪到 50–100 kg 时仍长期出现两条平行的体重带,这时秤上只容得下一头猪,只能是体重传感器出了故障。这样的猪会被标出来,原因写明”可能是称重异常”。

2. 同一个区间、同一批日子

FCR = ADFI ÷ ADG,只有当分子和分母来自同一段体重、同一批日子时,它才有意义。如果 ADG 按 30–120 kg 算,而 ADFI 按整个测定期的平均采食算,两头进站体重不同的猪就无法比较。

所以全流程只有一个区间 stage_range(默认 30–120 kg)。生长曲线确定每头猪进入和离开这个区间的日期,之后 ADG、ADFI、分段检查用的都是这批日子。改区间时,所有地方一起改:起止日期、要补齐的日子、适应期的采食是否计入、10 kg 分段,以及图中的虚线。

3. 先把区间补齐,再计算

缺记录是测定站的常态:猪某天没进站、耳标没读到、设备故障,或者进站晚、出栏早。与其在计算时绕开缺失,不如先把区间内每一天都补齐,补的方法随缺失的位置而不同:

缺失位置 体重 采食
两个有记录的日子之间 前后两天线性插值 ≤ 3 天:LOESS 平滑;> 3 天:群体曲线 × 个体比例
区间开头(进站晚) 切线外推 群体曲线 × 个体比例
区间末端(出栏早) 生长曲线 这头猪自己的”采食 ~ 体重”回归

背后的考虑是:中间缺失时,前后两天的实测最能说明这头猪当时的状态;两端缺失时没有实测可依,只能靠模型。晚进站的猪缺的是前期,它自己的数据里没有前期的信息,所以借用全群的曲线形状,每头猪只提供自己的采食水平;早出栏的猪缺的是末期,末期的上升趋势它自己的数据里已经有了,而全群曲线在高体重段变平,会低估它,所以末端用它自己的回归。这两个选择都来自无泄露的整体验证(validate_truncation()),而不是凭直觉。逐步示意见《填充方法》。用自己的数据验证过:中间缺失时,线性插值的日体重误差约 0.8 kg,用生长曲线约 1.1–1.6 kg。

补齐之后,ADG 就是区间内每天体重对日期回归的斜率。这个定义直观,和”每天长多少”的说法一致;有一两天的读数偏高或偏低,对斜率的影响也很小;R² 还能说明这头猪长得是否平稳。每一天的体重和它的来源(实测、插值、曲线)都保留在结果里,图中也用不同颜色标出,补了多少一目了然。

4. 标记,而不是删除

育种评估需要尽可能多的个体,而”不完美”不等于”不能用”。所以本包的原则是能算就算,算不准就标出来:

  • 只有数据确实不够时才剔除:有效体重少于 20 条、测定期短于 35 天、缺失率超过 30%;
  • 其他问题只降级为 low_confidence,原因写进 reason 或 fcr_note:进站太重、出栏太轻、两端填充超过 15 天、采食实测不足 70%、某个 10 kg 段记录断档等;
  • 没有任何数据被悄悄删掉:每条体重记录都有 qc_flag,每头被剔除的猪都在 $removed 中写明在哪一步、因为什么。

这样,用的人可以自己决定:育种评估只用 fcr_flag = "ok" 的个体,描述性统计用全部个体,或者在模型中把低可信度的个体区分开。

国家测定规程中的累计采食法曾作为可选方法实现过,后来删去了,原因正在于此。在示例数据上它会直接剔除大约一半的猪;分段料肉比还会因 n/(n−1) 的偏差系统性偏高,又引出更多的剔除;累计采食对体重的关系是向上弯的,用直线外推会低估 FCR。

5. 一套参数,放在一个对象里

所有阈值都集中在 qc_config() 返回的一个对象里,各函数通过 qc 参数接收,结果的 $settings 原样保存。这样做有三个好处:

  • 看得全:print(qc_config()) 一次列出全部参数,不用到各个函数里找;
  • 可复现:写论文或复查时,直接引用 $settings;
  • 可比较:同一个育种群体固定一套参数,年度之间的差异才来自猪,而不是方法。

早期版本提供过几套预设(casey、national、legacy),实际使用中反而让人困惑:预设之间差的是几十个参数的组合,很难说清楚差别来自哪里。1.0.0 起只保留一套默认方法,需要时逐个覆盖参数,每一处改动都看得见。

6. 方法有出处,选择可检验

每一步尽量用有文献依据的方法:采食错误判定用 Casey 等(2005)的 16 条规则,体重异常值和采食校正用 Jiao 等(2014)的稳健回归和混合模型,平滑用 Cleveland(1979)的稳健 LOESS。逐日回溯追踪是本包根据测定站的称重方式设计的,它的作用同样可以检验。

但没有一种方法在所有批次上都最好:晚进站的批次,二次曲线外推不稳,直线反而更好;成段缺失时 LOESS 略好于线性插值,两端缺失时两者一样。与其凭经验选择,本包提供了四个验证函数,在你自己的数据上故意加入误差或隐藏一部分记录,看哪种方法恢复得最好:

函数 检验什么
validate_outliers() 体重异常值方法
validate_adg() 生长曲线模型
validate_weight_fill() 体重填充方法
validate_adfi() 采食填充方法

验证的结论也反过来影响了默认设置。例如几项验证都说明:保证区间两端有记录,比选择哪种方法更重要,所以两端填充超过 15 天的猪会被标为低可信度。

7. 统一的数据入口

NEDAP 和 FIRE 的导出格式完全不同:列名、时间格式、单位都不一样,同一种设备不同软件版本也会有差别。如果每个分析函数都去适应这些差异,代码会越来越乱,也容易出错。

所以本包只在入口处理差异:read_station() 按”站点格式”把各种导出对应到同一张标准表,之后的分析只认这张表。列名对不上时,把格式写成一个小文本文件,同一种导出只需写一次。耳标号一律按文本读入,前导零不会丢失;单位统一为 g 和 kg,时间统一为时间型。

8. 为使用者着想

  • 中文文档:测定站的技术人员和育种人员是主要使用者;
  • 按测定站出图:每站一张图,每头猪一个分面,体重和采食的来源用颜色区分,核查问题时一眼能看出是哪头猪、哪一段;
  • 结果直接能用:write_results() 导出的 csv 带 BOM,Excel 打开中文不乱码;
  • 大数据也能跑:逐头猪的计算支持并行,长步骤有进度条;约 1650 头猪、175 万条访问记录,单核跑完全流程约 1.5 分钟;
  • 依赖少:只依赖 cli、data.table、ggplot2,以及 R 自带的 MASS 和 nlme,在测定站的电脑上也容易安装。

9. 局限

  • 所有填充方法和验证都假设缺失是随机的。实际中,猪生病时采食少,也更容易缺记录,这种偏差既验证不出来,也无法靠换方法消除。
  • 中途明显停止生长的猪(例如生病),生长曲线到不了区间终点,只能算覆盖到的那一段(adg_type = "partial"),并标为低可信度。本包不会为它编造一段”本该有”的生长。
  • 方法和阈值是在有限几个测定站的数据上定下来的。换一个测定站或设备,建议先跑一遍验证,再决定是否调整参数。

参考文献

  • Casey, D. S., Stern, H. S., & Dekkers, J. C. M. (2005). Identification of errors and factors associated with errors in data from electronic swine feeders. Journal of Animal Science, 83, 969-982.
  • Cleveland, W. S. (1979). Robust locally weighted regression and smoothing scatterplots. Journal of the American Statistical Association, 74, 829-836.
  • Jiao, S., Maltecca, C., Gray, K. A., & Cassady, J. P. (2014). Feed intake, average daily gain, feed efficiency, and real-time ultrasound traits in Duroc pigs: I. Journal of Animal Science, 92, 2377-2386.