You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 10:52:36