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)
}
请帮助!
答案 0 :(得分:40)
您还可以使用cumsum
set.seed(1)
n <- 1000
x <- cumsum(sample(c(-1, 1), n, TRUE))
答案 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)
下面,
cumsum
并立即拉出样本。Reduce
执行求和。lapply
和unlist
返回一个向量,并遍历1000个1的实例,直接按名称调用该函数。seq
而不是rep
创建迭代变量。sapply
而不是lapply
/ unlist
。vapply
代替lapply
/ unlist
。replicate
的调用,默认值为simplify = TRUE。for
循环预先分配向量并填充它。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))
}