在分组数据上使用yardstick::rmse报错且结果异常的技术咨询
我来帮你拆解这个问题的原因,以及给出正确的解决办法:
问题原因分析
首先得搞清楚yardstick::rmse的工作逻辑:它第一个参数必须是包含真实值和预测值列的数据框,而不是单独传递向量。
第一次报错的原因:
当你在summarise里写yardstick::rmse(truth = obs, estimate = pred)时,obs和pred被当成独立的数值向量传递给了函数,但rmse的第一个参数需要是数据框,所以会抛出no applicable method for 'rmse' applied to an object of class "c('double', 'numeric')"的错误。传入
.后结果异常的原因:
在dplyr的summarise调用中,.指代的是整个原始数据集,而不是当前分组的子数据框!所以每个分组计算时,都是用全部3行数据来算RMSE,得到的自然是同一个结果(sqrt((0+1+4)/3)≈1.29),而不是每个组自己的RMSE。
正确的解决办法
这里提供几种可行的方案,你可以根据习惯选择:
方案1:用cur_data()获取当前分组数据(推荐)
cur_data()是dplyr提供的函数,会返回当前分组的子数据框,正好符合rmse的参数要求:
library(yardstick) library(dplyr) dat <- structure(list(model = structure(1:3, .Label = c("A", "B", "C"), class = "factor"), obs = c(1, 1, 1), pred = 1:3), .Names = c("model", "obs", "pred"), row.names = c(NA, -3L), class = "data.frame") dat %>% group_by(model) %>% summarise(RMSE = rmse(cur_data(), truth = obs, estimate = pred)$.estimate)
运行后会得到你预期的结果:
# A tibble: 3 × 2 model RMSE <fct> <dbl> 1 A 0 2 B 1 3 C 2
方案2:用reframe替代summarise
reframe比summarise更灵活,可以直接处理rmse返回的tibble结果:
dat %>% group_by(model) %>% reframe(rmse(., truth = obs, estimate = pred)) %>% select(model, RMSE = .estimate)
方案3:直接手动计算RMSE(简单直观)
如果不需要依赖yardstick包,直接用基础公式计算反而更直接:
dat %>% group_by(model) %>% summarise(RMSE = sqrt(mean((obs - pred)^2)))
总结
yardstick的metric函数都是面向数据框设计的,在分组操作时一定要确保传递给它的是当前分组的子数据框,而不是整个数据集或单独的向量。用cur_data()或者reframe都能很好地解决这个问题,当然手动计算也是个不错的选择。
内容的提问来源于stack exchange,提问作者markus

