使用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
相关产品推荐
相关产品推荐

