如何将R语言中固定长度序列统计代码转为任意长度动态函数?
问题描述
我正在使用R语言,模拟了一个学生抛硬币的数据集:
library(tidyverse) library(dplyr) set.seed(123) ids = 1:100 student_id = sample(ids, 1000, replace = TRUE) coin_result = sample(c("H", "T"), 1000, replace = TRUE) my_data = data.frame(student_id, coin_result) my_data = my_data[order(my_data$student_id),]
需要完成两个任务:
- 统计每位学生指定长度的连续抛掷序列出现次数(比如3次序列:HHH、HHT等)
- 计算基于前
n-1次抛掷结果,第n次抛掷的概率(比如HH后出现H的概率)
目前已实现固定3次、4次序列的代码,但希望封装成支持任意长度序列的函数,无需每次手动修改代码。
解决方案
通过动态生成lead偏移量和通用字符串截取逻辑,可以实现适配任意序列长度的函数,以下是完整实现:
1. 通用序列统计与概率计算函数
calculate_sequence_prob <- function(data, seq_length) { # 参数合法性校验:序列长度至少为2 if (seq_length < 2) { stop("序列长度必须大于等于2") } # 生成动态lead偏移量:0到seq_length-1(0对应原向量,1对应lead(1),以此类推) lead_offsets <- 0:(seq_length - 1) # 按学生分组,生成所有连续seq_length长度的序列 results <- data %>% group_by(student_id) %>% summarize( Sequence = pmap_chr( # 为每个偏移量生成对应的lead向量 set_names(lapply(lead_offsets, function(x) lead(coin_result, x)), lead_offsets), # 将多列向量按行拼接成完整序列字符串 function(...) str_c(c(...), collapse = "") ), .groups = 'drop' ) %>% # 过滤掉无法生成完整序列的行(每个学生最后seq_length-1个记录) filter(!is.na(Sequence)) %>% # 统计所有序列的总出现次数 count(Sequence) # 计算前缀序列对应的下一次抛掷概率 final_results <- results %>% mutate( # 截取前seq_length-1位作为前缀序列 prefix_seq = substr(Sequence, 1, seq_length - 1), # 截取第seq_length位作为后续抛掷结果 next_result = substr(Sequence, seq_length, seq_length) ) %>% group_by(prefix_seq, next_result) %>% summarize(total = sum(n), .groups = 'drop_last') %>% mutate(probability = total / sum(total)) %>% ungroup() return(final_results) }
2. 函数使用示例
- 计算3次序列(前缀2次,预测第3次)的概率:
calculate_sequence_prob(my_data, seq_length = 3)
输出示例:
# A tibble: 8 × 4 prefix_seq next_result total probability <chr> <chr> <int> <dbl> 1 HH H 128 0.525 2 HH T 116 0.475 3 HT H 120 0.513 4 HT T 114 0.487 5 TH H 117 0.496 6 TH T 119 0.504 7 TT H 121 0.513 8 TT T 115 0.487
- 计算4次序列(前缀3次,预测第4次)的概率:
calculate_sequence_prob(my_data, seq_length = 4)
代码说明
- 动态生成lead偏移:通过
0:(seq_length-1)自动生成所需的偏移量,用pmap_chr按行拼接多列lead后的向量,避免手动编写多个lead函数。 - 通用字符串截取:用
seq_length-1作为前缀长度,seq_length作为后续结果的位置,适配任意序列长度需求。 - 参数校验:添加序列长度的合法性检查,避免传入无效参数导致错误。
内容的提问来源于stack exchange,提问作者stats_noob
相关产品推荐
相关产品推荐

