加速R码以计算马尔可夫链中的(高阶)跃迁
我写了一个小R代码段来遍历一个包含马尔可夫链实现的向量,并返回给定顺序的观察到的转换。 具体来说,假设我们对状态空间$\mathcal{S}$的2阶转换感兴趣。 最终目标是以方便的形式存储计数$n{ijk}$,$i,j,k\in\mathcal{S}$,以供以后使用加速R码以计算马尔可夫链中的(高阶)跃迁,r,performance,R,Performance,我写了一个小R代码段来遍历一个包含马尔可夫链实现的向量,并返回给定顺序的观察到的转换。 具体来说,假设我们对状态空间$\mathcal{S}$的2阶转换感兴趣。 最终目标是以方便的形式存储计数$n{ijk}$,$i,j,k\in\mathcal{S}$,以供以后使用 get_contingency_array <- function(seq, order){ N <- length(seq) states <- sort(unique(seq)) nstates &
get_contingency_array <- function(seq, order){
N <- length(seq)
states <- sort(unique(seq))
nstates <- length(states)
inds <- seq_along(states)
K <- order + 1
out <- array(0, dim = rep(nstates, K))
for (z in K:N){
pos <- match(seq[(z - K + 1):z], states)
s1 <- paste0("out[", paste(pos, collapse = ","), "]")
s2 <- paste(s1, "<-", s1, "+ 1")
eval(parse(text = s2))
}
return(out)
}
set.seed(666)
X1 <- rbinom(1E5, size = 1, prob = .8)
get_contingency_array(X1, 3)
我的问题是:怎样才能大大加快速度?对于较大的尺寸,它会有一点拖拉。除了最极端的情况外,在所有情况下都应该避免使用eval(parse(.)
第一次切割使用一种鲜为人知的方法在带有矩阵的数组上建立索引。为了演示,我将中断第一个For
循环的函数调用,并显示修改后数组上的索引:
debug(获取意外事件数组)
获取意外事件数组(X1,3)
###单步执行直到“for”循环,第一次通过:
Z
# [1] 4
###暂时重新分配'out'以显示索引
等等,我非常困惑。为什么eval
将代码存储为循环中的文本?直接对表达式求值即可。代码更简单,速度也将大大加快。(编辑:啊,明白了。直接看下面的答案。)除了使用matrix(…,nrow=1)
之外,你还可以使用t(…)
,它稍微短一点。没错,虽然目标不是编码高尔夫,而是性能,t(.)
似乎慢了10-15%(不确定为什么)。非常感谢你的帮助。我知道eval(parse)
会减慢速度,但我不知道如何摆脱它。回答得好@r2evans呃,好吧,这太可怕了(可能是因为t
是一个泛型)。值得一提的是,我的理由不是代码高尔夫(!?!),而是可读性。
, , 1, 1
[,1] [,2]
[1,] 148 624
[2,] 613 2567
, , 2, 1
[,1] [,2]
[1,] 601 2583
[2,] 2550 10310
, , 1, 2
[,1] [,2]
[1,] 613 2527
[2,] 2578 10327
, , 2, 2
[,1] [,2]
[1,] 2590 10310
[2,] 10304 40752