如何修正R语言n序列频率统计函数,补全遗漏的末尾序列?
一、修复遗漏最后一个序列的问题
原函数的索引范围写错了——对于长度为L的序列,长度为n的连续子序列总数是L - n + 1,原代码里用了1:(length(results) - n),少算了最后一个子序列的位置。把索引范围改成1:(length(results) - n + 1)就能解决问题:
n_sequences <- function(n, results) { helper <- function(i, n) if (n < 1) "" else sprintf( "%s%s", helper(i, n - 1), results[i + n - 1] ) result <- data.frame( table( sapply( 1:(length(results) - n + 1), # 此处修改索引范围 function(i) helper(i, n) ) ) ) colnames(result) <- c("Sequence", "Frequency") result } # 测试验证 Results <- c(0,0,0,1,1,1,0,1,0,1,1) n_sequences(4, Results)
运行后结果会包含遗漏的1011序列。
二、其他统计连续序列频率的方法
1. stringr包简洁实现
把数字序列转成字符串,直接滑动截取所有长度为n的子串再统计:
library(stringr) count_sequences_str <- function(n, results) { seq_str <- paste(results, collapse = "") sequences <- str_sub(seq_str, start = 1:(nchar(seq_str)-n+1), end = n:(nchar(seq_str))) result <- as.data.frame(table(sequences)) colnames(result) <- c("Sequence", "Frequency") result } count_sequences_str(4, Results)
2. zoo包rollapply滑动窗口
用滑动窗口函数直接处理向量,代码更简洁:
library(zoo) count_sequences_roll <- function(n, results) { sequences <- rollapply(results, width = n, FUN = function(x) paste(x, collapse = "")) result <- as.data.frame(table(sequences)) colnames(result) <- c("Sequence", "Frequency") result } count_sequences_roll(4, Results)
3. 基础R向量化方法(替代递归)
递归的helper函数效率偏低,用矩阵索引生成所有子序列更高效:
count_sequences_base <- function(n, results) { L <- length(results) idx_matrix <- matrix(1:(L - n + 1) + rep(0:(n-1), each = L - n + 1), ncol = n) sequences <- apply(idx_matrix, 1, function(idx) paste(results[idx], collapse = "")) result <- as.data.frame(table(sequences)) colnames(result) <- c("Sequence", "Frequency") result } count_sequences_base(4, Results)
三、计算条件概率的思路
以“出现三个0后,下一个数字是1的概率”为例,本质是:P(下一个是1 | 前三个是0) = 序列"0001"的频率 / 所有以"000"开头的序列总频率
可以通过统计n长度序列和n-1长度前缀序列的频率,匹配后计算:
calc_conditional_prob <- function(prefix, n, results) { # 统计n长度序列频率 seq_n <- count_sequences_str(n, results) # 统计n-1长度前缀序列频率 seq_n_minus_1 <- count_sequences_str(n-1, results) # 筛选以目标前缀开头的n长度序列 target_seqs <- seq_n[startsWith(seq_n$Sequence, prefix), ] # 获取目标前缀的总出现频率 prefix_freq <- seq_n_minus_1[seq_n_minus_1$Sequence == prefix, "Frequency"] # 计算每个后缀的条件概率 target_seqs$ConditionalProb <- target_seqs$Frequency / prefix_freq target_seqs } # 测试:三个0之后下一个是1的概率 calc_conditional_prob("000", 4, Results)
内容的提问来源于stack exchange,提问作者stats_noob
相关产品推荐
相关产品推荐

