R语言动物移动计算函数报错:非数值参数传入二元运算符
问题说明
用户有一份动物移动数据集data,格式如下:
Data ID Time x y u v A 2008-02-01 12:00:00 9155834.12606686 -1085858.899 -0.248678702 0.244811689 A 2008-02-02 12:00:00 9156464.06545883 -1085782.058 -0.251412658 0.247100772 A 2008-02-03 12:00:00 9156466.83719953 -1085785.249 -0.251420536 0.247112624 A 2008-02-04 12:00:00 9160775.91409932 -1083780.819 -0.273312639 0.262021876
使用以下R函数计算熊的移动距离:
bear_move <- function(data) { #make sure data is ordered properly data <- data[order(data$ID, data$time),] #identify last locations for each bear last_locs <- c(which(data$ID[-1] != data$ID[-nrow(data)]), nrow(data)) ## start point of step start <- as.matrix(data[,c("x", "y")]) #end point of step end <- rbind(as.matrix(start[-1,]), NA) #difference in time between steps (first to NEXT location) dt <- c(as.numeric(difftime(data$time[2:nrow(data)],data$time[1:nrow(data)-1], units="hours")), NA) #u and v components of ice drift uv <- as.matrix(data[,c("u", "v")]) ## calculate change in x,y abd u,v delta_xy <- end - start delta_uv <- uv*dt #initialize matrix for bear movement delta_bear <- matrix(NA, nrow=nrow(delta_xy), ncol=2) # idenitify which u/v estimates are NA notNA <- which(!is.na(delta_uv)) #bear move = x-u and y-v delta_bear[notNA] <- delta_xy[notNA] - delta_uv[notNA] # bear move == delta_xy for NA estimates delta_bear[-notNA] <- delta_xy[-notNA] #calculate bear movement with Pythagorean Theorem bear_move <- sqrt(rowSums(delta_bear^2)) #put NA for last step for each bear bear_move[last_locs] <- NA return(bear_move) }
执行bear_move(data)时触发错误:
Error in end - start : non-numeric argument to binary operator
错误排查与解决方法
核心错误原因
- 列名大小写不匹配:数据集中时间列名为
Time(首字母大写),但函数中多次使用data$time(小写),导致排序失败、时间差计算错误,甚至引入非数值类型数据。 end矩阵类型异常:rbind(as.matrix(start[-1,]), NA)中单独的NA是逻辑类型,与数值矩阵绑定后,整个end矩阵被强制转换为字符类型,无法和数值型的start矩阵做减法运算。- 时间差计算的索引错误:
data$time[1:nrow(data)-1]写法有误,未加括号的情况下会先计算nrow(data)-1,再取前N个元素,导致索引长度不匹配。
分步修复
1. 修正列名引用
将函数中所有data$time替换为data$Time,匹配数据集列名:
data <- data[order(data$ID, data$Time),] dt <- c(as.numeric(difftime(data$Time[2:nrow(data)], data$Time[1:(nrow(data)-1)], units="hours")), NA)
2. 修复end矩阵的类型问题
将末尾的NA改为数值型的c(NA, NA),保证end矩阵始终为数值类型:
end <- rbind(start[-1,], c(NA, NA)) # 注:start已经是矩阵,无需重复as.matrix
3. 修正时间差的索引逻辑
把data$time[1:nrow(data)-1]调整为data$Time[1:(nrow(data)-1)],避免索引长度错误:
dt <- c(as.numeric(difftime(data$Time[2:nrow(data)], data$Time[1:(nrow(data)-1)], units="hours")), NA)
4. 优化last_locs的计算(可选)
用基础R的ave函数简化写法,避免手动索引出错:
last_locs <- which(ave(seq(nrow(data)), data$ID, FUN = function(x) x == max(x)))
修复后的完整函数
bear_move <- function(data) { # 确保数据按ID和时间排序 data <- data[order(data$ID, data$Time),] # 识别每个个体的最后一行位置 last_locs <- which(ave(seq(nrow(data)), data$ID, FUN = function(x) x == max(x))) # 起始点矩阵 start <- as.matrix(data[, c("x", "y")]) # 终点矩阵:移除第一行后补数值型NA end <- rbind(start[-1,], c(NA, NA)) # 计算时间差(小时) dt <- c(as.numeric(difftime(data$Time[2:nrow(data)], data$Time[1:(nrow(data)-1)], units = "hours")), NA) # 冰漂流的u、v分量矩阵 uv <- as.matrix(data[, c("u", "v")]) # 计算x/y变化量和冰漂流的总位移 delta_xy <- end - start delta_uv <- uv * dt # 初始化熊的移动矩阵 delta_bear <- matrix(NA, nrow = nrow(delta_xy), ncol = 2) # 处理非NA的冰漂流数据 notNA <- which(!is.na(delta_uv)) delta_bear[notNA] <- delta_xy[notNA] - delta_uv[notNA] # NA值的冰漂流数据直接用x/y变化量 delta_bear[-notNA] <- delta_xy[-notNA] # 计算移动距离 bear_move <- sqrt(rowSums(delta_bear^2)) # 每个个体的最后一行设为NA bear_move[last_locs] <- NA return(bear_move) }
使用验证
修复后执行data$bear_move <- bear_move(data),即可为数据集添加熊的移动距离列。
内容的提问来源于stack exchange,提问作者Cam
相关产品推荐
相关产品推荐

