R语言马尔可夫链模拟:正确使用break语句终止序列
R马尔可夫链吸收态模拟修正方案
原修改代码存在以下核心错误:
- 函数无显式返回值:R函数默认返回最后执行的语句结果,原代码最后执行的是for循环结构,无有效返回值,因此运行后得到NULL
- 循环逻辑错误:嵌套
repeat会在同一序列位置反复重采样直到抽到1或5,完全违背马尔可夫链逐次转移的规则,且抽到终止值后没有跳出外层生成逻辑 - 预分配固定长度向量不符合需求:首次命中1/5的步数是随机的,提前分配固定长度
n的输出向量会残留无效空值,也未覆盖初始值本身就是1/5的边界场景
修正后的单链模拟函数
# 初始分布与转移矩阵定义 alpha <- c(0,1,0,0, 0) mat <- matrix(c(1,0,0,0,0, 0.2,0.2,0.5,0.05,0.05, 0.3,0.1,0.1,0.2,0.3, 0.2,0.2,0.2,0.2,0.2, 0,0,0,0,1), nrow = 5, ncol = 5, byrow = TRUE) chainSim <- function(alpha, trans_mat, max_step = 1000) { # 生成初始状态 chain <- sample(1:5, 1, prob = alpha) # 初始状态为吸收态直接返回 if (chain[1] %in% c(1, 5)) return(chain) # 逐次转移直到命中吸收态 repeat { current_last <- tail(chain, 1) next_state <- sample(1:5, 1, prob = trans_mat[current_last, ]) chain <- c(chain, next_state) # 命中吸收态终止循环 if (next_state %in% c(1, 5)) break # 最大步数保护,避免转移矩阵设置错误导致无限循环 if (length(chain) >= max_step) { warning("达到最大模拟步数仍未命中吸收态,已终止模拟") break } } return(chain) }
单次运行测试:
> chainSim(alpha, mat) [1] 2 3 2 4 4 3 1
批量100次模拟实现
由于每次命中吸收态的步数随机,生成的序列长度不一致,直接转等长data.frame会报错,先以列表存储再对齐即可:
# 重复模拟100次,结果存为列表 sim <- replicate(n = 100, expr = chainSim(alpha, mat), simplify = FALSE) # 对齐长度补NA,转为数据框 max_chain_len <- max(sapply(sim, length)) sim_final <- as.data.frame( t(sapply(sim, function(x) c(x, rep(NA, max_chain_len - length(x))))) )
你提供的转移矩阵中状态1和5都是吸收态(转移到自身的概率为1),命中后序列不会再发生状态变化,停止生成的逻辑完全符合吸收马尔可夫链的模拟规则。
内容的提问来源于stack exchange,提问作者stats_noob
相关产品推荐
相关产品推荐

