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

使用loess拟合时预测值观测数少一个的问题求助

问题

使用Rafa所著数据科学书籍中的波多黎各死亡数据集练习绘制平滑函数,将日期转为数值型后,以60天对应的span(span=60/1205)拟合loess模型,原数据集date和deaths均为1205条无NA观测,但拟合后得到的预测值只有1204条。测试更小数据集时,拟合结果观测数与原数据一致。

附上代码:

library(tidyverse)
library(purrr)
library(pdftools)
library(dslabs)
fn <- system.file("extdata", "RD-Mortality-Report_2015-18-180531.pdf",
                  package="dslabs")
dat <- map_df(str_split(pdf_text(fn), "\n"), function(s){
  s <- str_trim(s)
  header_index <- str_which(s, "2015")[1]
  tmp <- str_split(s[header_index], "\\s+", simplify = TRUE)
  month <- tmp[1]
  header <- tmp[-1]
  tail_index <- str_which(s, "Total")
  n <- str_count(s, "\\d+")
  out <- c(1:header_index, which(n == 1),
           which(n >= 28), tail_index:length(s))
  s[-out] %>% str_remove_all("[^\\d\\s]") %>% str_trim() %>%
    str_split_fixed("\\s+", n = 6) %>% .[,1:5] %>% as_tibble() %>%
    setNames(c("day", header)) %>%
    mutate(month = month, day = as.numeric(day)) %>%
    gather(year, deaths, -c(day, month)) %>%
    mutate(deaths = as.numeric(deaths))
}) %>%
  mutate(month = recode(month,"JAN" = 1, "FEB" = 2, "MAR" = 3,
                        "APR" = 4, "MAY" = 5, "JUN" = 6,
                        "JUL" = 7, "AGO" = 8, "SEP" = 9,
                        "OCT" = 10, "NOV" = 11, "DEC" = 12)) %>%
  mutate(date = make_date(year, month, day)) %>%
  filter(date <= "2018-05-01")


span=60/1205

smooth1<-loess(deaths~as.numeric(date),span=span, degree=1, data = dat)
解决方案

问题原因

这是loess模型的边界点自动丢弃问题:当span设置得极小(此处约0.0498,仅用60个观测点构建局部回归),数据集的第一个观测点无法让loess滑动窗口收集到足够的相邻数据满足拟合要求,因此会被自动跳过,导致预测值数量比原数据少1条。小数据集因窗口覆盖比例更高,不会触发该边界丢弃逻辑。

解决办法

  • 调整span参数
    不要用观测数比例计算span,改用时间跨度比例,更贴合“60天窗口”的实际需求,同时避免span过小:

    total_days <- as.double(max(dat$date) - min(dat$date))
    span <- 60 / total_days
    smooth1 <- loess(deaths ~ as.numeric(date), span = span, degree = 1, data = dat)
    
  • 强制生成所有点的预测值
    使用predict()函数并显式指定newdata为原数据集的所有日期,确保边界点也被计算:

    smooth1 <- loess(deaths ~ as.numeric(date), span = 60/1205, degree = 1, data = dat)
    dat$fitted <- predict(smooth1, newdata = dat)
    # 此时dat$fitted会有1205条观测
    
  • 检查日期唯一性
    确认日期是否存在重复值(重复日期可能导致loess处理异常):

    anyDuplicated(dat$date)
    

    若返回值大于0,需先去重或聚合后再拟合。

内容的提问来源于stack exchange,提问作者Carlos Chacon

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 20:13:15