用sapply()理解R卷积码

时间:2016-10-01 17:54:05

标签: r convolution sapply

我试图在this post中拆分R代码:

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. ;q}内的sapply()结尾的目的是什么?
  2. 它与<<-符号有何关联,旨在使z可以在sapply()的“隐含”循环之外访问?
  3. 下面你可以看到我的问题“黑客”这行代码:

    (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.
    

2 个答案:

答案 0 :(得分:3)

如果您希望在函数继续时看到z的中间值,请在下面的代码中插入catprint命令:

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)

  1. ;q}内的sapply()结尾的目的是什么?
  2. 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
    }
    
    1. 它与<<-符号有何关联,旨在使z可以在sapply()的“隐含”循环之外访问?
    2. 在R中,如果您使用<<-搜索?'<<-'运算符的文档,则说明

        

      运算符<<->>-通常仅在函数中使用,并导致通过父环境进行搜索,以便为要分配的变量的现有定义。如果找到诸如变量(并且其绑定未被锁定),则重新定义其值,否则在全局环境中进行赋值。

      在函数convolve.binomial中,值z在函数的本地定义。因此z <<-实际上重新定义了z函数中的convolve.binomial

      总而言之,z <<-调用中的sapply会更改z中已定义的convolve.binomial变量,并最终返回此z;q}内不需要sapply()个结尾。