为何基于时间差的if函数在R语言for循环中报错?
解决动物观测数据分组循环的报错问题
我一眼就看出你这个报错的问题啦——你的for循环边界没处理好!
先给你拆解下错误原因:你写的循环是for(i in 1:length(wilde16$DateTime)),而你的wilde16数据有16行,所以i会从1跑到16。当i=16的时候,wilde16$DateTime[i+1]就是第17个元素,可你的数据根本没有这一行,结果就是NA。这时候计算NA - wilde16$DateTime[16]得到的还是NA,而if语句必须要TRUE或FALSE才能判断,遇到缺失值就直接抛出那个missing value where TRUE/FALSE needed的错误了。你单独测i=1没问题,是因为那时候i+1=2是存在的,但最后一次循环就踩坑了。
那怎么修正呢?有两种办法:
方法一:修正你的for循环
把循环的范围改成从1到行数减1,避免访问不存在的元素,最后再单独处理最后一行的分组:
z <- 0 # 先初始化Group列,避免出现缺失值 wilde16$Group <- 0 for(i in 1:(nrow(wilde16)-1)){ if(wilde16$DateTime[i+1] - wilde16$DateTime[i] < 600){ wilde16$Group[i] <- z } else{ z <- z + 1 wilde16$Group[i] <- z } } # 最后一行的分组和前一行保持一致 wilde16$Group[nrow(wilde16)] <- wilde16$Group[nrow(wilde16)-1]
方法二:用R风格的向量操作替代for循环(更高效简洁)
其实在R里处理这种分组问题,完全不用写for循环,用diff()和cumsum()就能搞定,代码更短还不容易出错:
# 计算相邻观测的时间差,第一个元素设为601(确保第一个组从1开始) time_intervals <- c(601, diff(wilde16$DateTime)) # 每当时间差超过10分钟(600秒),就开启新组,用cumsum累计分组编号 wilde16$Group <- cumsum(time_intervals > 600)
这个方法的逻辑是:diff()计算相邻时间的差值,我们给第一个位置补一个大于600的值,这样第一个观测会被分到第1组,之后每次时间差超过600,cumsum就会加1,自动生成连续的分组编号。
内容的提问来源于stack exchange,提问作者Tommaso Saccà
相关产品推荐
相关产品推荐

