如何用R语言基于n阶马尔可夫链转移矩阵生成适配不同n的样本?
问题:基于n阶马尔可夫转移矩阵生成样本(无依赖第三方包)
我已经用R语言构建出n阶马尔可夫链的转移矩阵,代码如下:
set.seed(1) dat <- sample(c("A", "B", "C"), size = 2000, replace = TRUE) # 生成模拟数据 n <- 2 # 马尔可夫链阶数 if (n > 1) { from <- head(apply(embed(dat, n)[, n:1], 1, paste, collapse = ""), -1) to <- dat[-1:-n] } else { from <- dat[-length(dat)] to <- dat[-1] } fromTo <- data.frame(cbind(from, to)) TM <- table(fromTo) TM <- TM / rowSums(TM) # 归一化后的转移矩阵
但我没法写出适配任意n值的样本生成代码,希望找到不依赖markovchain包的可行方法(不同R版本对该包兼容性差)。
解决方案
核心逻辑:n阶马尔可夫链的下一个状态仅由当前连续的n个状态决定。生成样本时,先确定长度为n的初始状态序列,之后每一步根据当前的n状态组合,从转移矩阵中抽样得到下一个状态,再更新当前状态组合(去掉最旧的状态,加入新状态),循环此过程即可生成任意长度的样本。
以下是封装好的适配任意n值的函数:
generate_markov_samples <- function(transition_matrix, n_order, initial_states, sample_length) { # 参数说明: # transition_matrix: 已构建好的n阶转移矩阵(table格式) # n_order: 马尔可夫链的阶数 # initial_states: 初始状态序列,长度必须等于n_order # sample_length: 需要生成的总样本长度(包含初始状态) if (length(initial_states) != n_order) { stop("初始状态序列长度必须等于马尔可夫链阶数n_order") } current_state_str <- paste(initial_states, collapse = "") samples <- initial_states for (i in (n_order + 1):sample_length) { if (!current_state_str %in% rownames(transition_matrix)) { stop(paste("转移矩阵中不存在状态组合:", current_state_str)) } probs <- transition_matrix[current_state_str, ] next_state <- sample(names(probs), size = 1, prob = probs) samples <- c(samples, next_state) initial_states <- c(initial_states[-1], next_state) current_state_str <- paste(initial_states, collapse = "") } return(samples) }
测试示例
基于你生成的转移矩阵,可按如下方式调用函数:
# 示例:生成长度为50的样本,初始状态设为c("A", "B") set.seed(123) # 设置随机种子保证结果可复现 initial <- c("A", "B") generated_samples <- generate_markov_samples(TM, n_order = n, initial_states = initial, sample_length = 50) # 查看生成的样本 print(generated_samples)
代码说明
- 先验证初始状态长度与阶数是否匹配,避免运行错误
- 每次循环将当前n个状态拼接成字符串,匹配转移矩阵的行名
- 使用
sample()结合转移概率抽样下一个状态 - 更新状态组合时,移除最左侧的旧状态、加入新状态,始终保持长度为n
该实现完全不依赖第三方包,且能适配任意正整数n值。
内容的提问来源于stack exchange,提问作者Matt 38
相关产品推荐
相关产品推荐

