2016-10-01 133 views
1

我試圖掰開將R代碼this post瞭解[R卷積碼sapply()

x <- c(0.17,0.46,0.62,0.08,0.40,0.76,0.03,0.47,0.53,0.32,0.21,0.85,0.31,0.38,0.69) 


convolve.binomial <- function(p) { 
    # p is a vector of probabilities of Bernoulli distributions. 
    # The convolution of these distributions is returned as a vector 
    # `z` where z[i] is the probability of i-1, i=1, 2, ..., length(p)+1. 
    n <- length(p) + 1 
    z <- c(1, rep(0, n-1)) 
    sapply(p, function(q) {z <<- (1 - q) * z + q * (c(0, z[-n])); q}) 
    z 
} 
convolve.binomial(x) 
[1] 5.826141e-05 1.068804e-03 8.233357e-03 3.565983e-02 9.775029e-02 
[6] 1.804516e-01 2.323855e-01 2.127628e-01 1.394564e-01 6.519699e-02 
[11] 2.141555e-02 4.799630e-03 6.979119e-04 6.038947e-05 2.647052e-06 
[16] 4.091095e-08 

我RStudio試過debugging,但它仍然是不透明的。

問題出在線:sapply(p, function(q) {z <<- (1 - q) * z + q * (c(0, z[-n])); q})

我想在調用convolve.binomial(x)p = q = x的上下文中。至少我得到了相同的結果,如果我拉的功能之外的線條和運行sapply(x, function(x) {z <<- (1 - x) * z + x * (c(0, z[-n])); x})

x <- c(0.17,0.46,0.62,0.08,0.40,0.76,0.03,0.47,0.53,0.32,0.21,0.85,0.31,0.38,0.69) 
n <- length(x) + 1 
z <- c(1, rep(0, n-1)) 
# [1] 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
sapply(x, function(x) {z <<- (1 - x) * z + x * (c(0, z[-n])); x}) 
z # Is extracted by calling it and contains the correct result 

我的問題是:

  1. 什麼是內sapply()結束;q}的目的是什麼?
  2. 它與<<-符號有什麼關係,意思是讓z可以在sapply()的「隱式」循環之外訪問?

下面你可以看到我的問題 「黑客」 這行代碼:

(x_complem = 1 - x) 
sapply(x, function(x) {z <<- x_complem * z + x * (c(0, z[-n])); x}) 
z # Returns 16 values and warnings 

z_offset = c(0, z[-n]) 
# [1] 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
sapply(x, function(x) {z <<- (1 - x) * z + x * z_offset; x}) 
z # Returns different values. 
+1

沒有'返回'語句的中間結果,r會返回最後eval的結果。它看起來功能的功能因此是3倍。要在全局範圍內聲明'z',計算'z',然後返回輸入'q'。 'q'作爲返回值可能只是爲了協助調試或者可能將其傳遞給另一個函數。 – varontron

+0

'z'變量既可以作爲中間結果的集合存儲庫,也可以作爲關注該變量的下一個位置的移位運算符。 –

+0

@ 42-你能否詳細說明在一個簡單的情況下會發生什麼操作,比如'x < - c(2,3','convolve.binomial(x)',我會很樂意接受答案。我理解了卷積的一般原理,但是我遇到了與這個'sapply()'函數協調的問題。 – Toni

回答

3

如果你想看到z的中間值作爲函數進行再插入無論是cat或在下面的代碼print命令:

sapply(x, function(x) {z <<- (1 - x) * z + x * (c(0, z[-n])); cat(z,"\n"); x}) 
#-------- 
0.83 0.17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0.4482 0.4736 0.0782 0 0 0 0 0 0 0 0 0 0 0 0 0 
0.170316 0.457852 0.323348 0.048484 0 0 0 0 0 0 0 0 0 0 0 0 
0.1566907 0.4348491 0.3341083 0.07047312 0.00387872 0 0 0 0 0 0 0 0 0 0 0 
0.09401443 0.3235858 0.3744046 0.1759272 0.03051648 0.001551488 0 0 0 0 0 0 0 0 0 0 
0.02256346 0.1491116 0.3357823 0.3267701 0.1410286 0.02356488 0.001179131 0 0 0 0 0 0 0 0 0 
snipped rest of output 

我想,這使得它更清晰的是正在發生的事情是每個中間步驟代表一系列事件的一組概率。每行的總和爲1.0,表示當可能有較少數量的二項式參數時個別計數存活的概率。最終的結果顯示了整個序列組裝完成後特定計數總和的概率。

另一個有趣的特徵是,這個結果在x中隨機重新排序的概率是不變的(因爲它應該是原始問題)。檢查從

plot(x) 
lines(seq(length(z)), z) 
z2 <- convolve.binomial(sample(x)) 
lines(seq(length(z)), z2, col="red") 
z3 <- convolve.binomial(sample(x)) 
lines(seq(length(z)), z3, col="blue") 
1
  1. 什麼是內sapply()結束;q}的目的是什麼?

sapply中的函數返回q,但實際上並不需要它。以下功能將工作相同。

convolve.binomial <- function(p) { 
    n <- length(p) + 1 
    z <- c(1, rep(0, n-1)) 
    sapply(p, function(q) {z <<- (1 - q) * z + q * (c(0, z[-n]))}) 
    z 
} 
  • 它如何涉及<<-符號,欲使z訪問的「隱式」環即sapply()之外?
  • 在R,如果你搜索了的文檔,使用?'<<-'它說,

    運營商<<->>-通常只在函數中使用<<-運營商,並導致搜索通過進行父環境中的變量的現有定義。如果找到諸如變量(並且其綁定沒有被鎖定),則其值被重新定義,否則分配發生在全局環境中。

    在函數convolve.binomial中,值z在該函數的本地定義。因此z <<-實際上在convolve.binomial函數中重新定義了z

    所以總結一下,在sapply呼叫z <<-改變z變量已經在convolve.binomial定義,我們最終回到這個z。在sapply()內不需要;q}結尾。

    +0

    你能拼寫這個調用的內部工作中的第一步是幾步? – Toni