使用lapply生成个体状态转移表时如何强制表维度一致?
解决状态转移表维度不一致的绘图问题
我懂你现在的困扰——150个个体里有的转移次数太少,甚至没转移,导致生成的状态转移表大小不一,不管是直接提取数据绘图还是手动补0都容易出问题。这里给你两个靠谱的解决方案,应该能解决你的问题:
方案1:生成table时固定维度(最简单直接)
问题的根源是table()默认只保留出现过的状态水平,所以没转移的状态会被省略。我们可以把FROM和TO转换成包含所有4个状态的因子,强制生成4x4的转移表,哪怕某个状态组合没有转移,也会填充0。
修改你的transition_table生成代码即可:
n_STATEs <- 4 data <- read.csv("transitiondata.csv") transitions <- by(data, data$ID, function(xx) { data.frame( ID = head(xx$ID,-1), TIME = tail(xx$TIME,-1), FROM = head(xx$STATE,-1), TO = tail(xx$STATE,-1) ) }) # 关键修改:把FROM和TO转为指定levels的因子,确保table是4x4结构 transition_table <- lapply(transitions, function(xx) { xx$FROM <- factor(xx$FROM, levels = 1:n_STATEs) xx$TO <- factor(xx$TO, levels = 1:n_STATEs) table(xx$FROM, xx$TO) }) # 后续绘图代码可以正常运行,因为每个table都是4x4的 min_n_transitions <- min(unlist(transition_table)) max_n_transitions <- max(unlist(transition_table)) max_freq <- 150 par(mfrow=rep(n_STATEs,2), mai=c(.4,.4,.4,.1)) for ( from in 1:n_STATEs ) { for ( to in 1:n_STATEs ) { # 提取每个个体的(from,to)转移次数 foo <- sapply(transition_table, "[", from, to) hist(foo, freq=TRUE, xlim=c(min_n_transitions,max_n_transitions), ylim=c(0,max_freq), xlab="", ylab="", main=paste("From",from,"to",to), las=1, col="lightgray") } }
这个方法能保证所有转移表的结构完全一致,不会出现维度错误,而且转移计数是准确的,不会因为行/列排序问题出错。
方案2:用三维数组统一存储转移计数(更灵活)
如果后续还要做更多分析,可以把所有个体的转移次数整理成一个三维数组(ID × FROM × TO),xtabs会自动处理缺失的转移组合,填充0,不需要手动补全。
代码示例:
n_STATEs <- 4 data <- read.csv("transitiondata.csv") transitions <- by(data, data$ID, function(xx) { data.frame( ID = head(xx$ID,-1), TIME = tail(xx$TIME,-1), FROM = head(xx$STATE,-1), TO = tail(xx$STATE,-1) ) }) # 合并所有个体的转移数据 all_transitions <- do.call(rbind, transitions) # 按ID、FROM、TO分组统计次数,缺失的组合自动补0 transition_counts <- xtabs(~ ID + FROM + TO, data = all_transitions, exclude = NULL, na.action = na.pass) # 绘图:直接提取每个(from,to)组合的所有个体次数 max_freq <- 150 par(mfrow=rep(n_STATEs,2), mai=c(.4,.4,.4,.1)) for (from in 1:n_STATEs) { for (to in 1:n_STATEs) { counts <- transition_counts[, from, to] hist(counts, freq=TRUE, xlim=c(min(counts), max(counts)), ylim=c(0,max_freq), xlab="", ylab="", main=paste("From",from,"to",to), las=1, col="lightgray") } }
这个方法的数据结构更清晰,后续做统计分析(比如计算平均转移次数、差异检验)会更方便。
为什么你之前的补全方法可能出错?
你之前手动补全缺失行/列时,rows和cols是从现有表中提取的唯一值,可能出现排序不一致的问题(比如某个表的行是c(2,1),而你补全时用的是1:4的顺序),导致提取的转移计数对应错误的状态组合。而用因子指定levels或者xtabs的方法,能严格保证状态的顺序和完整性,避免这类问题。
内容的提问来源于stack exchange,提问作者asher
相关产品推荐
相关产品推荐

