如何计算 r 中分布的重叠百分比?

How to calculate percent overlap in distributions in r?

我在下面有一个虚拟数据框,我想在其中计算站点分布之间的成对重叠百分比。基本上,site1 和 site2 重叠的百分比是多少,site2 与 site3 以及 site1 与 site3?

structure(list(site = c("site1", "site1", "site1", "site1", "site1", 
"site1", "site1", "site1", "site1", "site1", "site2", "site2", 
"site2", "site2", "site2", "site2", "site2", "site2", "site2", 
"site2", "site3", "site3", "site3", "site3", "site3", "site3", 
"site3", "site3", "site3", "site3"), total = c(0.4191, 0.2844, 
0.2611, 0.2743, 0.2938, 0.3287, 0.2992, 0.4062, 0.2946, 0.2671, 
0.3832, 0.3875, 0.3118, 0.4506, 0.4215, 0.4266, 0.3518, 0.4446, 
0.4255, 0.3208, 0.2377, 0.2818, 0.2526, 0.2425, 0.2973, 0.4539, 
0.357, 0.2865, 0.3624, 0.3026)), class = c("grouped_df", "tbl_df", 
"tbl", "data.frame"), row.names = c(NA, -30L), groups = structure(list(
    site = c("site1", "site2", "site3"), .rows = structure(list(
        1:10, 11:20, 21:30), ptype = integer(0), class = c("vctrs_list_of", 
    "vctrs_vctr", "list"))), row.names = c(NA, -3L), class = c("tbl_df", 
"tbl", "data.frame"), .drop = TRUE))

ggplot(aes(x = total, group = site, fill = site)) +
  geom_density(adjust = 1.5, alpha = 0.3) 

您的密度图可能有点误导,因为密度图会超出 x 轴上数据的实际范围,并且往往会给出比数据中实际存在的重叠更高的估计值。更好的可视化可能是:

df %>%
  group_by(site) %>%
  mutate(site = factor(site)) %>%
  summarize(xmin = min(total), xmax = max(total), 
            ymin = as.numeric(site), ymax = as.numeric(site)) %>%
  ggplot() +
  geom_segment(aes(x = xmin, xend = xmax, y = ymin, yend = ymax, color = site),
               size = 2) +
  scale_y_continuous(breaks = 1:3, expand = c(1, 1)) +
  theme_bw()
#> `summarise()` has grouped output by 'site'. You can override using the
#> `.groups` argument.

创建成对比较的一种方法是使用 expand.grid 获取所有唯一的网站对:

comp_df <- expand.grid(A = sort(unique(df$site)), 
                       B = sort(unique(df$site)))

然后我们需要一个函数来获取两个站点的名称并计算它们范围之间的重叠百分比。我在这里使用简单的算术以相当行人的方式进行此操作:

comp_func <- function(a, b) {
  max_a <- max(df$total[df$site == a])
  min_a <- min(df$total[df$site == a])
  max_b <- max(df$total[df$site == b])
  min_b <- min(df$total[df$site == b])
  max_b <- ifelse(max_b > max_a, max_a, max_b)
  min_b <- ifelse(min_b < min_a, min_a, min_b)
  (max_b - min_b) / (max_a - min_a)
}

现在我们可以 Map 将此函数应用于比较数据框的行,以便我们获得每个唯一站点对的成对估计值。

comp_df$overlap <- unlist(Map(comp_func, a = comp_df$A, b = comp_df$B))

最后,我们要删除测试区域是否与自身重叠的条目,因为这将始终为 100%:

comp_df <- comp_df[comp_df$A != comp_df$B,]

最后的结果可以对照我们的plot进行sense checked,可以看出是有道理的(overlap列是A列中的站点与B列中的站点重叠的比例)

comp_df
#>       A     B   overlap
#> 2 site2 site1 0.7730548
#> 3 site3 site1 0.7308048
#> 4 site1 site2 0.6791139
#> 6 site3 site2 0.6419981
#> 7 site1 site3 1.0000000
#> 8 site2 site3 1.0000000

因此,例如,我们可以看到站点 1 和站点 2 与站点 3 100% 重叠,正如我们可以在我们的图中确认的那样,而站点 1 与站点 2 重叠约 68%。

reprex package (v2.0.1)

于 2022-04-25 创建