如何修复交互矩阵生成时的subscript out of bounds错误?
问题:创建交互矩阵时出现下标越界错误
运行代码创建猪只交互矩阵时,出现以下错误:
Error in interaction_matrix[as.numeric(pig_id), as.numeric(closest_pig)] : subscript out of bounds
使用的代码如下:
create_interaction_matrices <- function(nm, behavior_code = "AFF", select_every = 10, nsel = 25) { NNdatafull <- read_excel(nm, sheet = 1) colnames(NNdatafull) <- c("Date", "Time", "Pen", "Pig_ID", "Distance", "Closest_Pig", "Behavior", "Orientation", "Location") datelevels <- unique(NNdatafull$Date) interaction_matrices <- list() for (date in datelevels) { mdat <- filter(NNdatafull, Date == date) mdat <- filter(mdat, Behavior == behavior_code) # Get unique pig IDs from both Pig_ID and Closest_Pig columns unique_pigs <- union(unique(mdat$Pig_ID), unique(mdat$Closest_Pig)) # Initialize interaction matrix with the size based on the number of unique pigs interaction_matrix <- matrix(0, nrow = length(unique_pigs), ncol = length(unique_pigs)) for (i in 1:nsel) { time <- min(mdat$Time) + (i - 1) * (60 * select_every) time_data <- filter(mdat, Time == time) interacting_pigs <- unique(time_data$Pig_ID) closest_pigs <- unique(time_data$Closest_Pig) # Update interaction matrix based on pig ID to closest pig interactions for (pig_id in interacting_pigs) { closest_pig <- time_data$Closest_Pig[time_data$Pig_ID == pig_id] # Increment the value in the interaction matrix interaction_matrix[as.numeric(pig_id), as.numeric(closest_pig)] <- interaction_matrix[as.numeric(pig_id), as.numeric(closest_pig)] + 1 } } interaction_matrices[[as.character(date)]] <- interaction_matrix } return(interaction_matrices) }
你推测的原因正确:矩阵维度由unique_pigs的数量决定,但部分Pig_ID的数值大于猪只总数(比如栏内仅13头猪,却存在ID为16的个体),直接用ID数值作为矩阵下标会超出范围。
解决方案:将猪ID映射为连续索引
核心思路是把非连续的猪ID转换成从1开始的连续整数索引,用索引作为矩阵下标,同时保留原ID作为矩阵的行/列名方便查看。修改后的代码如下:
create_interaction_matrices <- function(nm, behavior_code = "AFF", select_every = 10, nsel = 25) { NNdatafull <- read_excel(nm, sheet = 1) colnames(NNdatafull) <- c("Date", "Time", "Pen", "Pig_ID", "Distance", "Closest_Pig", "Behavior", "Orientation", "Location") datelevels <- unique(NNdatafull$Date) interaction_matrices <- list() for (date in datelevels) { mdat <- filter(NNdatafull, Date == date) mdat <- filter(mdat, Behavior == behavior_code) # 获取所有出现过的猪ID(包括Pig_ID和Closest_Pig) unique_pigs <- union(unique(mdat$Pig_ID), unique(mdat$Closest_Pig)) # 创建ID到连续索引的映射:每个ID对应1、2、3... pig_index <- setNames(seq_along(unique_pigs), unique_pigs) # 初始化矩阵,同时给行和列命名为原猪ID interaction_matrix <- matrix(0, nrow = length(unique_pigs), ncol = length(unique_pigs), dimnames = list(unique_pigs, unique_pigs)) for (i in 1:nsel) { time <- min(mdat$Time) + (i - 1) * (60 * select_every) time_data <- filter(mdat, Time == time) interacting_pigs <- unique(time_data$Pig_ID) # 更新交互矩阵:用映射后的索引代替原ID数值 for (pig_id in interacting_pigs) { closest_pig <- time_data$Closest_Pig[time_data$Pig_ID == pig_id] # 通过pig_index获取对应的索引 row_idx <- pig_index[as.character(pig_id)] col_idx <- pig_index[as.character(closest_pig)] interaction_matrix[row_idx, col_idx] <- interaction_matrix[row_idx, col_idx] + 1 } } interaction_matrices[[as.character(date)]] <- interaction_matrix } return(interaction_matrices) }
关键修改点说明:
- 新增
pig_index:用setNames创建一个命名向量,键是原猪ID,值是连续的整数索引(从1到length(unique_pigs)) - 初始化矩阵时添加
dimnames:把矩阵的行和列命名为原猪ID,后续查看矩阵时能直接对应到具体猪只 - 矩阵赋值时使用
row_idx和col_idx:通过pig_index把原ID转换成合法的矩阵下标,避免越界问题
这样修改后,无论猪ID是否连续,都能正确映射到矩阵的行/列,不会出现下标越界的错误,同时保留了原ID的可读性。
内容的提问来源于stack exchange,提问作者Carly O'Malley
相关产品推荐
相关产品推荐

