如何使用dplyr::group_by()实现分组loess回归?
解决分组LOESS回归的实用方案
我太懂你踩的这个坑了——dplyr::group_by压根不是为了让像loess()这种基础统计函数自动识别分组而生的,它只是给数据框打上分组标记,而loess()本身会直接忽略这个标记,对着整个数据集一顿拟合。别慌,给你几个靠谱的解决办法,都是日常做分组平滑常用的:
方法1:用dplyr::group_modify(dplyr原生推荐方案)
这个函数就是专门为分组后执行自定义操作设计的,完美适配你的需求。假设你的数据集是df,分组列是group_col,自变量为x,因变量为y,代码示例如下:
library(dplyr) # 分组拟合LOESS并生成平滑曲线点集 smoothed_results <- df %>% group_by(group_col) %>% group_modify(function(group_data, ...) { # 对当前分组数据拟合LOESS模型 loess_model <- loess(y ~ x, data = group_data) # 生成当前分组x范围内的100个预测点(可按需调整数量) pred_x <- seq(min(group_data$x), max(group_data$x), length.out = 100) pred_y <- predict(loess_model, newdata = data.frame(x = pred_x)) # 返回包含平滑结果的小数据框 data.frame(x = pred_x, y_smoothed = pred_y) }) %>% ungroup()
执行后smoothed_results里会按group_col分组存储每个组的平滑点,直接拿来绘图就可以了。
方法2:tidyr::nest + purrr::map(tidyverse经典工作流)
如果你习惯用嵌套数据框的思路,这个方法逻辑清晰,也很灵活:
library(dplyr) library(tidyr) library(purrr) smoothed_results <- df %>% group_by(group_col) %>% nest() %>% # 将每个分组的数据嵌套为列表列 mutate( # 对每个嵌套的分组数据拟合LOESS并生成平滑点 smoothed_data = map(data, function(group_data) { loess_model <- loess(y ~ x, data = group_data) pred_x <- seq(min(group_data$x), max(group_data$x), length.out = 100) pred_y <- predict(loess_model, newdata = data.frame(x = pred_x)) data.frame(x = pred_x, y_smoothed = pred_y) }) ) %>% unnest(smoothed_data) %>% # 展开嵌套的平滑结果 select(-data) %>% # 移除原始数据的列表列 ungroup()
方法3:基础R的by()函数(无额外包依赖)
如果不想加载太多tidyverse包,用基础R的by()函数也能搞定:
# 定义处理单个分组的函数 process_group <- function(group_data) { loess_model <- loess(y ~ x, data = group_data) pred_x <- seq(min(group_data$x), max(group_data$x), length.out = 100) pred_y <- predict(loess_model, newdata = data.frame(x = pred_x)) # 把分组信息添加回结果中 data.frame(group_col = unique(group_data$group_col), x = pred_x, y_smoothed = pred_y) } # 分组处理并合并结果 smoothed_list <- by(df, df$group_col, process_group) smoothed_results <- do.call(rbind, smoothed_list)
小提示
- 如果某个分组的数据量很小,LOESS可能会报错或拟合不稳定,可以调整
loess()中的span参数(比如调大一点,增加拟合的平滑度),或者设置degree = 1降低多项式阶数。 - 生成预测点时尽量不要超出当前分组的x范围,避免无意义的外推导致结果失真。
内容的提问来源于stack exchange,提问作者Alex Nesta
相关产品推荐
相关产品推荐

