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

含条件中断的while循环计算时长:代码无法识别End_Focal问题排查

问题排查与解决方案

核心错误原因

  1. 连续Out_Sight区间被重复计算
    你的代码中,外层for循环会遍历每一行j,只要该行是Out_Sight就会计算从j到停止点k的时长。但当存在连续多行Out_Sight时,每一行都会触发一次计算——比如Out_Sight从行2到行5,j=2时计算5-2,j=3时计算5-3,j=4时计算5-4,这些值会被重复累加到总和中,导致最终时长被严重高估。

  2. stop使用list类型不必要
    虽然%in%可以处理list,但使用向量更符合R的常规用法,避免潜在的类型匹配歧义。

修正后的代码

# 保留你的"not in"函数
'%!in%' <- function(x,y)!('%in%'(x,y))

# 处理时间列
df$HMS <- lubridate::hms(df$Time, roll = F)

# 初始化foc_summary(仅保留ObsID列)
library(dplyr)
foc_summary <- df %>% 
  mutate(ObsID = factor(ObsID)) %>% 
  group_by(ObsID) %>% 
  slice(1) %>%
  select(ObsID)
detach('package:dplyr')

foc_summary <- as.data.frame(foc_summary)

# 按ObsID和时间排序数据
df <- df[order(df$ObsID, df$HMS),]

# 将stop改为向量类型
stop <- c("In_Sight", "End_Focal")

# 初始化结果列
foc_summary$Time_OutSight <- 0

# 按ObsID计算视线外时长
for (i in 1:nrow(foc_summary)){
  current_obs <- foc_summary$ObsID[i]
  print(current_obs)
  
  obs_data <- droplevels(subset(df, df$ObsID == current_obs))
  total_out <- 0
  j <- 1
  
  while(j <= nrow(obs_data)){
    if (obs_data$Setting[j] == "Out_Sight"){
      # 找到当前Out_Sight区间的结束点
      k <- j + 1
      while(k <= nrow(obs_data) && obs_data$Setting[k] %!in% stop){
        k <- k + 1
      }
      
      # 处理边界:如果到观测末尾,取最后一行的时间
      end_time <- ifelse(k > nrow(obs_data), obs_data$HMS[nrow(obs_data)], obs_data$HMS[k])
      
      # 累加当前区间的时长
      total_out <- total_out + as.numeric(end_time) - as.numeric(obs_data$HMS[j])
      
      # 跳到区间结束点,避免重复处理
      j <- k
    } else {
      j <- j + 1
    }
  }
  
  foc_summary$Time_OutSight[i] <- total_out
}

关键修改说明

  • 改用while循环遍历行,处理完一个Out_Sight区间后直接跳到结束点k,彻底避免重复计算同一区间的时长。
  • 将stop从list改为向量,消除类型歧义。
  • 增加边界判断,处理Out_Sight持续到观测最后一行的情况,防止索引越界。
  • 简化累加逻辑,避免用c()不断扩展向量,提升代码效率。

内容的提问来源于stack exchange,提问作者Vittoria Roatti

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 16:02:56