如何避免在此R代码中声明全局变量?

时间:2015-03-10 04:25:09

标签: r ggplot2 idioms

我正在尝试修改Kyle Gorman's autoloess函数,使其可以作为ggplot2 stat_smooth中的方法进行调用。 autoloess是一个简单的包装器,它通过优化器运行loess,以找到最小化AICc的span的值。

我创建了一些成功运行的东西,但只能使用全局变量。是否有一种更优雅,更具风格的编程方式?

我的代码:

AICc.loess <- function(fit) {
  # compute AIC_C for a LOESS fit, from:
  # 
  # Hurvich, C.M., Simonoff, J.S., and Tsai, C. L. 1998. Smoothing 
  # parameter selection in nonparametric regression using an improved 
  # Akaike Information Criterion. Journal of the Royal Statistical 
  # Society B 60: 271–293.
  # 
  # @param fit        loess fit
  # @return           'aicc' value
  stopifnot(inherits(fit, 'loess'))
  # parameters
  n <- fit$n
  trace <- fit$trace.hat
  sigma2 <- sum(resid(fit) ^ 2) / (n - 1)
  return(log(sigma2) + 1 + 2 * (2 * (trace + 1)) / (n - trace - 2))
}


.autoloess.magic.w <- NULL
autoloess <- function(formula, data, weights, span=c(0.01, 2.0)) {
  .autoloess.magic.w <- ~weights
  fit <- loess(formula=formula, 
               data=data, 
               weights=.autoloess.magic.w)
  stopifnot(length(span) == 2)
  # loss function in form to be used by optimize
  f <- function(span) AICc.loess(update(fit, span=span))
  # find best loess according to loss function
  res <- update(fit, span=optimize(f, span)$minimum)
  cat(paste("Optimal span:", res$pars$span, "\n"))
  return(res)
}

快速测试:

# Test
library(ggplot2)
set.seed(1984)
# Create a cubic curve
df <- data.frame(x=1:2500, y=500000 +
                   (-1000*(1:2500)) +
                   ((1:2500)^2)  +
                   -0.00025*((1:2500)^3) +
                   rnorm(2500, sd=60000),
                 ww=runif(2500, min=0, max=10))
# Use loess span
ggplot(df, aes(x=x, y=y, weight=ww)) + geom_point() + stat_smooth(method="loess")

Loess smooth, with default span of 0.75

# Use autoloess
ggplot(df, aes(x=x, y=y, weight=ww)) + geom_point() +  stat_smooth(method="autoloess")

Loess smooth, with optimised span of 0.47

1 个答案:

答案 0 :(得分:1)

您可以使用weight变量(调用该函数时似乎存在):

autoloess <- function(formula, data, weights, span=c(0.01, 2.0)) {

  fit <- loess(formula = formula, 
               data = data, 
               weights=weight)

  stopifnot(length(span) == 2)

  # loss function in form to be used by optimize
  f <- function(span) AICc.loess(update(fit, span=span))
  # find best loess according to loss function
  res <- update(fit, span=optimize(f, span)$minimum)
  cat(paste("Optimal span:", res$pars$span, "\n"))
  return(res)
}