【问题标题】:Coverage of overlapping segments with R使用 R 覆盖重叠段
【发布时间】:2021-07-27 14:50:56
【问题描述】:

我有这个数据框:

example_data <- data.frame(Start = c(1,10,25, 40, 2, 11, 27, 50),
           End = c(9, 26, 30, 41, 14, 16, 40, 55),
           Group = c('A','A','A','A','B','B','B','B'))
Start End Group
1 9 A
10 26 A
25 30 A
40 41 A
2 14 B
11 16 B
27 40 B
50 55 B

考虑到某些行相互重叠,我想知道每个组的长度或覆盖范围。例如,第二行从 26 开始,第三行从 25 开始。所以有一个单元的重叠。

这将是我想要达到的结果:

Group Coverage
A 29
B 32

我试过这个,只有在没有重叠的情况下才有效。

example_data %>% 
    group_by(Group) %>% 
    summarise(coverage = sum(End - Start))

但我不知道如何处理重叠段。有什么线索吗?

【问题讨论】:

  • 可以有多个重叠,例如2-10、3-11 和 4-12?另外,除了整数,还能有其他值吗?
  • 是的,我的真实数据集中可能有多个重叠。不,只有整数。

标签: r


【解决方案1】:

代码说明-

  • group_by 不言自明
  • pmax 是 max(平行最大值)的矢量化版本。它将返回一个相同长度的向量,而不是长度为 1 的向量(如 max 的情况)。
  • lag 获取我们之前的值(默认位置参数是 1)
  • 因此,我正在服用
    • 总和
      • 的区别
        • End, &
        • End 的先前值和Start 的当前值的最大值

希望够清楚

是的,通过添加 .groups = 'drop',您可以取消 group_by 语句的分组,而无需添加 ungroup() 的另一个特定步骤

library(tidyverse)

example_data <- data.frame(Start = c(1,10,25, 40, 2, 11, 27, 50),
                                 End = c(9, 26, 30, 41, 14, 16, 40, 55),
                                 Group = c('A','A','A','A','B','B','B','B'))

example_data %>%
  group_by(Group) %>%
  summarise(Coverage = sum(End - pmax(Start,  lag(End, default = 0))), .groups = 'drop')
#> # A tibble: 2 x 2
#>   Group Coverage
#>   <chr>    <dbl>
#> 1 A           29
#> 2 B           32

reprex package (v2.0.0) 于 2021-07-27 创建

【讨论】:

  • 如果有多个重叠,这是否有效?
  • 是的,我更新了dplyr 并完成了这项工作。谢谢,让我检查它是否适用于多个重叠,我会接受它。
  • @CodingBiology,你说的多重重叠是什么意思?如果可能存在多行重叠条件,请编辑您的示例!可以修改代码以适应这种情况
  • 谢谢@AnilGoyal,您介意解释一下pmaxlag,尤其是.groups = 'drop' 的功能吗?我只想不断进步。谢谢
  • 亲爱的@AnilGoyal,感谢您的明确解释!现在更清楚了:)
【解决方案2】:

这将适用于多个重叠,但仅适用于整数:

library(purrr)

your_data %>%
  split(~Group) %>%
  map(~ .x %>%
          pmap(list) %>%
          reduce(~ union(.x, seq.int(.y$Start, .y$End - 1)), .init = NULL)) %>%
  lengths() %>%
  tibble::tibble(Group = names(.), Coverage = .)

返回:

# A tibble: 2 x 2
  Group Coverage
  <chr>    <int>
1 A           29
2 B           32
# Data used:
your_data <- structure(list(Start = c(1L, 10L, 25L, 40L, 2L, 11L, 27L, 50L), End = c(9L, 26L, 30L, 41L, 14L, 16L, 40L, 55L), Group = c("A", "A", "A", "A", "B", "B", "B", "B")), row.names = c(NA, -8L), class = c("tbl_df", "tbl", "data.frame"))

【讨论】:

    猜你喜欢
    • 2015-03-31
    • 2022-01-17
    • 2013-10-19
    • 1970-01-01
    • 2011-11-12
    • 1970-01-01
    • 1970-01-01
    • 2018-08-01
    • 2021-09-15
    相关资源
    最近更新 更多