10

Xn 可以取值 -1 或 1,概率为 0.5。并且 Sn= Sn-1 + Xn 我如何计算由 Sn = X1 + X2 + : : : + Xn 在时间 n 观察到的部分和。我正在尝试在这里模拟随机游走。我做了以下但我不确定它是正确的:

rw <- function(n){
    x=numeric(n)
    xdir=c(TRUE, FALSE)
    step=c(1,-1)
    for (i in 2:n)
    if (sample(xdir,1)) {
        x[i]=x[i-1]+sample(step,1)
    } else {
        x[i]=x[i-1]
    }
    list(x=x)
}

请帮忙!

4

4 回答 4

47

您也可以使用cumsum

set.seed(1)

n <- 1000
x <- cumsum(sample(c(-1, 1), n, TRUE))

在此处输入图像描述

于 2014-02-24T15:01:00.770 回答
4

这个答案只是为了解释为什么您的代码不起作用。@jake-burkhead 提供了您实际编写代码的方式。

在这段代码中,你只做了一半的时间。这是因为您正在从中取样xdir以决定是否移动。相反,我会在循环中向您推荐以下内容:

for(i in 2:n){
  x[i] <- x[i - 1] + sample(step, 1)
}

sample(step, 1)调用决定 walk 是移动1还是-1

要计算部分总和,您可以cumsum()在生成x. 结果将是步行中给定点的部分和的向量。

于 2014-02-24T14:59:15.580 回答
4

这篇文章解决了用于此计算的各种基本 R 方法的时间安排。这篇文章的灵感来自对这篇文章的评论和@josilber 在帖子中对 Jake Burkhead 发布的最快方法的评论。

下面,使用多种方法来计算随机游走。为此,每个函数提取 1000 个 1 或 -1 值,fnc如下所述。计时测试microbenchmark对每种方法使用 1000 次重复。

fnc <- function(n) sample(c(1L, -1L), n, replace=TRUE)
library(microbenchmark)
microbenchmark(all=cumsum(fnc(1000L)),
      reduce=Reduce("+", fnc(1000L), accumulate=TRUE),
      laplyRpCln=cumsum(unlist(lapply(rep.int(1L, 1000L), fnc))),
      laplyRpAn=cumsum(unlist(lapply(rep.int(1L, 1000L), function(x) fnc(1L)))),
      laplySqAn=cumsum(unlist(lapply(seq_len(1000L), function(x) fnc(1L)))),
      saplyRpCln=cumsum(sapply(rep.int(1L, 1000L), fnc)),
      saplyRpAn=cumsum(sapply(rep.int(1L, 1000L), function(x) fnc(1L))),
      saplySqAn=cumsum(sapply(seq_len(1000L), function(x) fnc(1L))),
      vaplyRpCln=cumsum(vapply(rep.int(1L, 1000L), fnc, FUN.VALUE=0)),
      vaplyRpAn=cumsum(vapply(rep.int(1L, 1000L), function(x) fnc(1L), FUN.VALUE=0)),
      vaplySqAn=cumsum(vapply(seq_len(1000L), function(x) fnc(1L), FUN.VALUE=0)),
      replicate=cumsum(replicate(1000L, fnc(1L))),
      forPre={vals <- numeric(1000L); for(i in seq_along(vals)) vals[i] <- fnc(1L); cumsum(vals)},
      forNoPre={vals <- numeric(0L); for(i in seq_len(1000L)) vals <- c(vals, fnc(1L)); cumsum(vals)},
      times=1000)

这里,

  • "all" 使用了 Jake Burkhead 的建议,cumsum一次全部提取样本。
  • “减少”立即提取样本,但用于Reduce执行求和。
  • laplyRpCln 使用lapplyandunlist返回一个向量并遍历 1 的 1000 个实例,直接按名称调用该函数。
  • laplyRpAn 的不同之处在于使用匿名函数。
  • laplySqAn 使用匿名函数并使用seq而不是创建迭代变量rep
  • saplyRpCln, laplyRpAn, laplySqAn 与 laplyRpCln 等相同,只是它sapply被调用而不是lapply/ unlist
  • vaplyRpCln 等与 laplyRpCln 等相同,vapply只是用于代替lapply/ unlist
  • 复制是对 的调用replicate,其中默认为简化=真。
  • forPre 使用一个for循环来预先分配向量并填充它。
  • forNoPre 使用一个for循环来创建一个空numeric(0)向量,然后用于c连接到该向量。

这返回

Unit: microseconds
       expr      min         lq        mean     median         uq      max neval     cld
        all   25.634    31.0705    85.66495    33.6890    35.3400 49240.30  1000 a      
     reduce  542.073   646.7720   780.13592   696.4775   750.2025 51685.44  1000  b     
 laplyRpCln 4349.384  5026.4015  6433.60754  5409.2485  7209.3405 58494.44  1000   c e  
  laplyRpAn 4600.200  5281.6190  6513.58733  5682.0570  7488.0865 55239.04  1000   c e  
  laplySqAn 4616.986  5251.4685  6514.09770  5634.9065  7488.1560 54263.04  1000   c e  
 saplyRpCln 4362.324  5080.3970  6325.66531  5506.5330  7294.6225 59075.02  1000   cd   
  saplyRpAn 4701.140  5386.1350  6781.95655  5786.6905  7587.8525 55429.02  1000     e  
  saplySqAn 4651.682  5342.5390  6551.35939  5735.0610  7525.4725 55148.32  1000   c e  
 vaplyRpCln 4366.322  5046.0625  6270.66501  5482.8565  7208.0680 63756.83  1000   c    
  vaplyRpAn 4657.256  5347.2190  6724.35226  5818.5225  7580.3695 64513.37  1000    de  
  vaplySqAn 4623.897  5325.6230  6475.97938  5769.8130  7541.3895 14614.67  1000   c e  
  replicate 4722.540  5395.1420  6653.90306  5777.3045  7638.8085 59376.89  1000   c e  
     forPre 5911.107  6823.3040  8172.41411  7226.7820  9038.9550 56119.11  1000      f 
   forNoPre 8431.855 10584.6535 11401.64190 10910.0480 11267.5605 58566.27  1000       g

请注意,第一种方法显然是最快的。接下来是一次提取完整样本,然后Reduce用于执行求和。在*apply函数中,“干净”的版本,直接使用函数的名称,性能似乎有小幅提升,lapply版本似乎与 相当vapply,但考虑到取值范围,这个结论并不完全直截了当。sapply似乎是最慢的,尽管函数调用的方法支配了*apply函数的类型。

两个for循环的表现最差,预分配for循环的表现优于for增长的循环c

在这里,我在 openSuse 42.1 上运行 3.4.1 的补丁版本(大约 2017 年 8 月 23 日补丁)。

如果您发现任何错误,请告诉我,我会尽快修复它们。感谢 Ben Bolker 促使我进一步研究最终功能,在那里我发现了一些错误。

于 2017-08-27T00:10:12.093 回答
0

这是一种方法。

GenerateRandomWalk <- function(k = 250,initial.value = 0) {
  # Add a bionomial at each step
  samples = rbinom(k,1,0.5)
  samples[samples==0] = -1
  initial.value + c(0, cumsum(samples))
}
于 2014-02-24T21:38:05.573 回答