2010-11-17 25 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,sumlxsumx)才能使其運行; optimize找不到它們,如果我只使用<-將它們設置在函數內部。我嘗試將它們設置在optimize之內,但那也不起作用。謝謝你的幫助。

Charlie

+0

我有點困惑。它看起來像人們所期望的那樣行事:如果c2ll是全局定義的,那麼詞法範圍會要求任何變量查找首先在c2ll中發生,然後在全局中發生。如果將c2ll的所有輸入定義爲函數參數,那麼混淆會更少。 – 2010-11-17 07:54:36

回答

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 2010-11-17 13:15:39

+0

謝謝。固定 – 2010-11-17 14:56:12

1

您的simResults函數返回一個邏輯向量。而不是使用rowMeans,只需使用平均(simResults),結果看起來相當明智的......至少在某種程度上是:

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

謝謝,迪文。是的,該函數工作正常,但我想知道爲什麼我需要使用'<< - '在全局環境中設置ML統計信息以便'optimize'找到它們,而如果我只在使用'<-','optimize'的函數環境沒有找到它們。看起來有點古怪,我不喜歡在函數之外定義變量(即全局)。 – Charlie 2010-11-17 06:04:50

+0

我意識到可能存在範圍問題,因此將c2ll函數作爲chi2c主體中的第一行。這並沒有產生預期的結果,我的建議改爲意味着(simResults)是我從那裏進行調試的結果。 – 2010-11-17 15:06:02

1

您的問題源於R使用的詞法範圍規則。詳見language definitions手冊。總之,你的函數c2ll正在尋找它定義的環境中的變量。

爲了避免這個問題,你必須將n,sum1x和sum2x明確地作爲參數傳遞給你的函數,或者直接在ch2c函數中本地定義你的函數。

這是一個很常見的問題,SO上有很多有趣的例子。