2010-11-17 3 views
2

У меня есть следующая функция, которая извлекает некоторые данные из дистрибутива хи-квадрат и сравнивает распределение 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 
} 

Эта функция делает только то, что я хотел бы и точен, но я не понимаю, почему мне нужно установить статистику максимального правдоподобия (n, sumlx и sumx) во всем мире, чтобы заставить его работать; optimize не находит их, если я только устанавливаю их внутри функции, используя <-. Я попытался установить их внутри optimize, но это тоже не сработало. Спасибо за вашу помощь.

Charlie

+0

Я немного смущен.Кажется, что он ведет себя так, как можно было бы ожидать: если c2ll определяется глобально, тогда лексическая область потребует, чтобы все переменные сначала выполнялись в c2ll, а затем глобально. Было бы меньше путаницы, если бы вы определили c2ll как имеющую все свои входы в качестве параметров функции. –

ответ

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 

Оба являются чистыми вариантами, которые сохраняют инкапсуляцию ваших функций.

+0

В последнем предложении вашего первого абзаца есть ошибка: динамическая дважды? – John

+0

спасибо. исправлено –

1

Функция simResults возвращает логический вектор. Вместо того чтобы использовать rowMeans, просто использовать средние (simResults) и результаты выглядят достаточно разумно ... по крайней мере в той степени, в которой:

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

Спасибо, DWin. Да, функция работает нормально, но мне интересно, почему мне нужно использовать '<< -', чтобы установить статистику ML в глобальной среде, чтобы «оптимизировать», чтобы найти их, тогда как, если я определяю их только в пределах среда функций, использующая '<-',' optimize', не находит их. Кажется немного причудливым, и мне не очень нравится определять переменные вне функции (т. Е. Глобально). – Charlie

+0

Я понял, что может быть проблема с определением области обзора, и поэтому функция c2ll помещается как первая строка в теле chi2c. Это не принесло ожидаемых результатов, и мое предложение изменить значение (simResults) стало результатом моих отладочных усилий оттуда. –

1

Ваша проблема связана с лексическими правилами определения области видимости, которые использует R. См. Больше в руководстве language definitions. Короче говоря, ваша функция c2ll ищет переменные в среде, в которой она была определена.

Чтобы избежать этой проблемы, вы должны явно передавать значения n, sum1x и sum2x в качестве аргументов вашей функции или непосредственно определять свою функцию локально в функции ch2c.

Это довольно распространенный вопрос, есть много интересных примеров на SO.

Смежные вопросы