'optimize'没有在函数调用中找到变量

时间:2010-11-17 04:50:44

标签: r statistics

我有以下函数从卡方分布中提取一些数据,并使用最大似然比较X的分布与已知的卡方分布。此过程模拟nSims次。 (我将这些结果与排列测试的结果进行比较,但不包括该代码。)

chi2c <- function(xdf=2, yObs=100, xObs=100, nSims=1000, nPerm=500, alpha=0.05){
  simResults <- sapply(1:nSims, function(x){
    # Draw variables
    x  <- rchisq(xObs, df=xdf)
    # Other variables not relevant here
    # [[snip]]

    # Permutation test
    # [[snip]]

    # Calculate the statistics necessary for maximum likelihood
    n       <<- length(x)
    sumlx   <<- sum(log(x))
    sumx    <<- sum(x)
    # Calculate the maximum likelihood estimate
    dfhat   <- optimize(f=c2ll, interval=c(1, 10), maximum=TRUE)$maximum
    # Calculate the test statistic: -2 times the log likelihood ratio
    llr     <- -2 * (c2ll(2) - c2ll(dfhat))
    # Compare the test statistic to its asymptotic dist: chi-squared
    lReject <- llr > qchisq(1 - alpha, df=1)

    # Provide the results
    # [[snip]]
  })
  # Calcuate means across simulations
  rowMeans(simResults)
}

此函数调用c2ll,卡方似然函数

c2ll <- function(dfHat){
  -n * log(gamma(dfHat/2)) - n * (dfHat/2) * log(2) + 
  (dfHat/2 - 1) * sumlx - sumx/2
}

此功能正是我想要的并且准确无误,但我不明白为什么我必须设置最大似然统计数据(nsumlxsumx)在全球范围内开展工作;如果我只使用optimize在函数内设置它们,则<-找不到它们。我尝试在optimize内设置它们,但这也不起作用。谢谢你的帮助。

查理

3 个答案:

答案 0 :(得分:2)

R具有词法范围,这意味着函数在定义它们的环境中查找变量。 c2ll在全局环境中定义,因此它在函数内部看不到n,sumx和sum1x的定义。另一方面,S使用动态范围,其行为与期望的一样(即,它在调用它的范围内查找变量)。计算机科学家普遍认为,动态范围界定是一个死路一条的坏主意,而词汇范围界定是可行的方法。

实际上,你能做些什么呢?

嗯,有几种选择......

首先,您可以在本地定义您的功能:

n       <- length(x)
sumlx   <- sum(log(x))
sumx    <- sum(x)
c2ll <- function(dfHat){
    -n * log(gamma(dfHat/2)) - n * (dfHat/2) * log(2) + (dfHat/2 - 1) * sumlx - sumx/2
}
dfhat   <- optimize(f=c2ll, interval=c(1, 10), maximum=TRUE)$maximum

第二,您可以让c2ll获取其他参数,并通过优化传递这些参数。

#in global env
c2ll <- function(dfHat,n,sum1x,sumx){
  -n * log(gamma(dfHat/2)) - n * (dfHat/2) * log(2) + 
  (dfHat/2 - 1) * sumlx - sumx/2
}

#...
#in function
n       <- length(x)
sumlx   <- sum(log(x))
sumx    <- sum(x)
dfhat   <- optimize(f=c2ll, interval=c(1, 10), n=n,sum1x=sum1x,sumx=sumx, maximum=TRUE)$maximum

两者都是干净的选项,可以保留函数的封装。

答案 1 :(得分:1)

您的simResults函数返回逻辑向量。而不是使用rowMeans,只需使用mean(simResults),结果看起来合理合理......至少在以下程度:

> chi2c(alpha=0.05)
[1] 0.057
> chi2c(alpha=0.5)
[1] 0.503

答案 2 :(得分:1)

您的问题源于R使用的词汇范围规则。请参阅language definitions手册中的更多内容。简而言之,您的函数c2ll正在查找已定义的环境中的变量。

为了避免这个问题,你必须将n,sum1x和sum2x明确地作为函数的参数传递,或者直接在ch2c函数中本地定义你的函数。

这是一个非常常见的问题,SO上有很多有趣的例子。