R语言中计算环形布置陷阱的中位步距问题求助
环形陷阱中位距离计算问题解决
问题背景
需要按池塘和年份分组,计算捕获小龙虾的环形布置陷阱之间的中位距离。陷阱沿池塘岸线环形排列,距离取最短路径(比如10个陷阱的池塘中,陷阱1和9的距离为2而非8),且不计算同一陷阱间的距离。
示例数据集构建代码
# Create vectors for each column Pond <- c("Aubrees", "Aubrees", "Kohls", "Kohls") Year <- c(2019, 2020, 2019, 2020) TrapNumbers <- list(c(1, 9, 2, 3, 6), c(3, 4, 9, 2, 5), c(3, 4, 9, 2), c(1, 9, 2, 3)) NumberofTraps <- c(10, 10, 12, 12) # Initialize an empty vector to store all TrapCaught values TrapCaught <- numeric() # Iterate over the lists of TrapNumbers to combine them into one vector for (trap_list in TrapNumbers) { TrapCaught <- c(TrapCaught, trap_list) } # Create the dataframe DF <- data.frame(Pond = rep(Pond, sapply(TrapNumbers, length)), Year = rep(Year, sapply(TrapNumbers, length)), NumberofTraps = rep(NumberofTraps, sapply(TrapNumbers, length)), TrapCaught = TrapCaught)
手动计算预期结果
- Aubrees 2019:距离值为[2,1,2,5,3,4,3,1,4,3],中位值=3
- Aubrees 2020:距离值为[1,4,1,2,5,2,1,3,4,3],中位值=2.5
- Kohls 2019:距离值为[1,6,1,5,2,5],中位值=3.5
- Kohls 2020:距离值为[4,1,2,5,6,1],中位值=3
错误代码及问题
以下代码输出的中位值为2、2.5、2.5、2.5,与预期结果不符:
library(dplyr) # Function to calculate pairwise distances between two vectors pairwise_distances <- function(x) { n <- length(x) outer(x, x, "-") %% n } # Calculate the median distance for each group median_distances <- DF %>% group_by(Pond, Year) %>% summarize(median_distance = median(pairwise_distances(TrapCaught)[upper.tri(pairwise_distances(TrapCaught))])) # Print the result print(median_distances)
问题分析与修正方案
错误原因
- 取模基数错误:原函数用捕获到小龙虾的陷阱数量
length(x)作为环形取模的基数,实际应该用该池塘的总陷阱数(NumberofTraps)。 - 未取最短路径:环形距离需要取差值取模后,与总陷阱数的一半比较,保留较小的那个值,才是实际最短距离。
修正后的代码
library(dplyr) # 修正后的环形成对距离计算函数 pairwise_circular_distances <- function(trap_ids, total_traps) { # 生成所有成对差值的绝对值 diffs <- abs(outer(trap_ids, trap_ids, "-")) # 环形取模得到原始距离 mod_diffs <- diffs %% total_traps # 取最短路径:选择环形两侧中较短的距离 shortest_dists <- pmin(mod_diffs, total_traps - mod_diffs) # 提取上三角部分,排除同一陷阱和重复计算的成对组合 shortest_dists[upper.tri(shortest_dists)] } # 分组计算中位距离 median_distances <- DF %>% group_by(Pond, Year) %>% summarize( median_distance = median(pairwise_circular_distances(TrapCaught, first(NumberofTraps))), .groups = "drop" # 取消分组状态 ) print(median_distances)
运行上述代码后,输出结果将与手动计算的预期值完全一致:
# A tibble: 4 × 3 Pond Year median_distance <chr> <dbl> <dbl> 1 Aubrees 2019 3 2 Aubrees 2020 2.5 3 Kohls 2019 3.5 4 Kohls 2020 3
内容的提问来源于stack exchange,提问作者William Ota
相关产品推荐
相关产品推荐

