You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

R语言处理时间向量时if条件出现NA值报错的原因咨询

解决R中if条件出现NA值的报错问题

首先,咱们先搞清楚你遇到的报错根源:error in if missing value where true/false needed 这个错误,本质是if条件判断里出现了NA值,而if语句只能接受TRUE/FALSE的逻辑值,NA会直接触发报错。

为什么会出现NA?

看你代码里的dayafterday循环:

dayafterday <- for (time_idx in 2:taille) {
  if (time_trunc[time_idx] != time_trunc[time_idx-1]) {
    row_to_keep[time_idx-1] <- TRUE
    if (time_idx > 2) {
      time_trunc[time_idx-1] <- time_trunc[time_idx-1] + 1
    }
    # 这里修改了time_trunc的长度!
    time_trunc <- time_trunc[row_to_keep]
    duree<- length(time_trunc)
    epidemies_time[epid_idx]<-duree
  }
}

问题出在循环过程中你修改了time_trunc的长度:当你执行time_trunc <- time_trunc[row_to_keep]后,time_trunc的长度会变短,但你的循环依然在按2:taille的范围执行。当time_idx超过新的time_trunc长度时,time_trunc[time_idx]就会返回NA,这时候time_trunc[time_idx] != time_trunc[time_idx-1]的结果就是NA,直接导致if报错。

另外还有一个潜在问题:在modele_epid循环中,如果infect[ind_idx] == 0,time[ind_idx+1]不会被重新赋值,会保持初始的0,这可能导致time_trunc里出现不符合预期的0值,但这不是本次报错的直接原因。

怎么修复这个问题?

方案1:修复原循环逻辑,避免在循环中修改向量长度

我们可以先完整标记所有需要保留的行,再一次性筛选,而不是在循环中动态修改time_trunc:

# 替换原来的dayafterday循环部分
time_trunc <- trunc(time)
row_to_keep <- rep(FALSE, taille)
row_to_keep[1] <- TRUE  # 保留第一个元素

for (time_idx in 2:taille) {
  if (!is.na(time_trunc[time_idx]) && time_trunc[time_idx] != time_trunc[time_idx-1]) {
    row_to_keep[time_idx] <- TRUE  # 标记当前不同的元素,而不是前一个
  }
}
# 一次性筛选出不重复的整数对应的行
unique_time_trunc <- time_trunc[row_to_keep]
duree <- length(unique_time_trunc)
epidemies_time[epid_idx] <- duree

这里做了两个关键调整:

  • 不在循环内修改time_trunc的长度,先遍历完所有元素标记需要保留的行
  • 增加!is.na(time_trunc[time_idx])的判断,提前过滤NA值,避免条件里出现NA

方案2:用R的内置函数简化需求(更高效)

其实你的核心需求是对time向量取整后,获取不重复的整数,再计算这个唯一值集合的长度,完全不需要复杂的for循环,用R的内置函数一行就能搞定:

duree <- length(unique(trunc(time)))
epidemies_time[epid_idx] <- duree

unique(trunc(time))会直接返回取整后的所有唯一值,length()就能得到你要的长度,代码更简洁,运行效率也更高。

完整修改后的代码片段

把方案2整合到你的完整代码里,替换原来的时间处理部分:

suscept<-rep(0,taille)
infect<-rep(0,taille)
remov<-rep(0,taille)
time<-rep(0,taille)
nvcas<-rep(0,taille)
pop_susc <- 0.1
infect[1]<-5
suscept[1]<- pop_susc*taille - infect[1]
remov[1]<- taille - infect[1]+suscept[1]
beta<-0.0000524
alpha<-0.4
epidemies_nb <- 60
epidemies_time <-c(1:epidemies_nb)

time_code <- for (epid_idx in 1:epidemies_nb) {
  modele_epid <- for(ind_idx in 1:(taille-1)) {
    if(infect[ind_idx]!=0) {
      s<--log(runif(1))/(beta*suscept[ind_idx]*infect[ind_idx]+alpha*infect[ind_idx])
      time[ind_idx+1]<-time[ind_idx]+s
      rand<-runif(1)
      proba<-beta*suscept[ind_idx]*infect[ind_idx]/(beta*suscept[ind_idx]*infect[ind_idx]+alpha*infect[ind_idx])
      if (rand<=proba) {
        suscept[ind_idx+1]<-suscept[ind_idx]-1
        infect[ind_idx+1]<-infect[ind_idx]+1
        remov[ind_idx+1]<-remov[ind_idx]
        nvcas[ind_idx+1]<-1
      } else {
        suscept[ind_idx+1]<-suscept[ind_idx]
        infect[ind_idx+1]<-infect[ind_idx]-1
        remov[ind_idx+1]<-remov[ind_idx]+1
        nvcas[ind_idx+1]<-0
      }
    }
  }
  # 用内置函数直接实现需求,避免循环报错
  duree <- length(unique(trunc(time)))
  epidemies_time[epid_idx] <- duree
  # 注意:每次循环后最好重置time向量,避免下一次迭代使用上一次的结果
  time <- rep(0, taille)
}

epidemies_time

另外加了一个小细节:每次迭代后重置time向量,避免下一次循环使用上一次的time值,保证每个epid_idx对应的time都是独立计算的。

内容的提问来源于stack exchange,提问作者Virgile Korsec

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 10:52:36