模拟随机游走

时间:2014-02-24 14:51:40

标签: r random-walk

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 个答案:

答案 0 :(得分:40)

您还可以使用cumsum

真正简洁有效地完成此操作
set.seed(1)

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

enter image description here

答案 1 :(得分:4)

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

在此代码中,您只能完成一半的时间。这是因为您从xdir开始抽样以决定是否移动。相反,我会在你的循环中推荐你以下内容:

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

sample(step, 1)来电决定步行是1还是-1

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

答案 2 :(得分:3)

这篇文章讨论了用于此计算的各种基本R方法的时序。这篇文章的灵感来自对this post的评论以及@josilber在帖子中对Jake Burkhead发布的最快方法的评论。

下面,使用各种方法来计算随机游走。为实现此目的,每个函数都会提取1000个值,如下面fnc中定义的1或-1。时序测试使用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”立即拉取样本,但使用Reduce执行求和。
  • laplyRpCln使用lapplyunlist返回一个向量,并遍历1000个1的实例,直接按名称调用该函数。
  • laplyRpAn使用匿名函数不同。
  • laplySqAn使用匿名函数并使用seq而不是rep创建迭代变量。
  • saplyRpCln,laplyRpAn,laplySqAn与laplyRpCln等相同,只是调用sapply而不是lapply / unlist
  • vaplyRpCln等与laplyRpCln等相同,只是使用vapply代替lapply / unlist
  • replicate是对replicate的调用,默认值为simplify = TRUE。
  • 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促使我更多地调查最终功能,在那里我发现了一些错误。

答案 3 :(得分: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))
}