如何从重复值中删除重叠的范围并保留关联值?

How to remove ranges that are overlapping from duplicated values and keep associated values?

我有一个数据框,其中有一些重复的 x 值。这些值与一个范围相关联。应该删除重复的值(重复的 x 值)和重叠范围(两条线在低列和上列中重叠),但我想保留它们引用的值(val colum)。

library(dplyr)
df = data.frame(x=c("A","A","A","B","B","B","C"),
           low = c(-10,-5,100,100,200,300,10),
           up = c(2,3,200,150,250,350,20), 
           val = c(1,2,150,125,225,325,15))
df
  x low  up val
1 A -10   2   1
2 A  -5   3   2
3 A 100 200 150
4 B 100 150 125
5 B 200 250 225
6 B 300 350 325
7 C  10  20  15

如您所见,第 1 行和第 2 行重叠。看着the example here。我试图编写一个 dplyr 代码,但它没有给我预期的结果。与示例的不同之处在于我不是 "merging" 2 个数据集。所以我不知道如何测试包含重复值的数据集中的不同范围。我正在考虑将数据集中的重复值分组并单独测试它们。但是由于没有集成到dplyr函数中,我觉得是不行的。

df.gr = df %>% 
  group_by(x)

df.gr[with(df.gr, low <= up),]

最后,我想要这样的东西

  x low  up val
1 A -10   3 1,2
2 A 100 200 150
3 B 100 150 125
4 B 200 250 225
5 B 300 350 325
6 C  10  20  15

如您所见,对于重叠的范围,我保留了两个范围中的最低值和最高值。另外,我想 "remember" 列中的值 "val"。这就是为什么我想在重叠的范围内得到 1,2。

此外,在我在这里引用的示例中,每个重复值只有 2 个范围。在我的例子中,我可以有 2 个或更多重复值。我想测试 any 重复值并测试它们的范围,看看它们是否重叠。

例如,

df = data.frame(x=c("A","A","A","A","B","B","B","C"),
           low = c(-10,-5,-2,100,100,200,300,10),
           up = c(2,3,4,200,150,250,350,20), 
           val = c(1,2,3,150,125,225,325,15))

df
  x low  up val
1 A -10   2   1
2 A  -5   3   2
3 A  -2   4   3
4 A 100 200 150
5 B 100 150 125
6 B 200 250 225
7 B 300 350 325
8 C  10  20  15

会给出:

  x low  up   val
1 A -10   4 1,2,3
2 A 100 200   150
3 B 100 150   125
4 B 200 250   225
5 B 300 350   325
6 C  10  20    15

我也试过在 tidy 中使用 spread 函数,但没有成功:

tidyr::spread(df,x,val)
  low  up   A   B  C
1 -10   2   1  NA NA
2  -5   3   2  NA NA
3  -2   4   3  NA NA
4  10  20  NA  NA 15
5 100 150  NA 125 NA
6 100 200 150  NA NA
7 200 250  NA 225 NA
8 300 350  NA 325 NA

基本上,如果我想使用它,我必须将低列和高列作为键 ,但我不能那样做。此外,每个重复值的重叠数量会使数据报的大小在创建不同的列时发生变化。所以我不知道如何继续这个...

这可行。我相信您需要在粘贴命令中使用 "collapse"。

output <- df %>% group_by(x) %>% summarise(low = min(low), up = max(up), values = paste(val,collapse=","))

这输出这个 df:

structure(list(x = structure(1:3, .Label = c("A", "B", "C"), class = "factor"), 
    low = c(-10, 100, 10), up = c(200, 350, 20), values = c("1,2,3,150", 
    "125,225,325", "15")), class = c("tbl_df", "tbl", "data.frame"
), .Names = c("x", "low", "up", "values"), row.names = c(NA, 
-3L))

# A tibble: 3 x 4
       x   low    up      values
  <fctr> <dbl> <dbl>       <chr>
1      A   -10   200   1,2,3,150
2      B   100   350 125,225,325
3      C    10    20          15

编辑:查看复杂递归解决方案的编辑历史

这是一个简单的解决方案,我们创建一个布尔值来标识组的变化,这个布尔值的 cumsum 给我们一个组标识符,我们在这个标识符上使用 group_by 然后总结值。

library(dplyr)
# Example 1
df = data.frame(x=c("A","A","A","B","B","B","C"),
                low = c(-10,-5,100,100,200,300,10),
                up = c(2,3,200,150,250,350,20), 
                val = c(1,2,150,125,225,325,15))

df %>% arrange(x,low) %>%
  group_by(x,set = cumsum(c(TRUE,x[-1] != x[-n()] | low[-1] > up[-n()]))) %>%
  summarize(low=min(low),up=max(up),val=lst(val)) %>%
  print.data.frame

#   x set low  up  val
# 1 A   1 -10   3 1, 2
# 2 A   2 100 200  150
# 3 B   3 100 150  125
# 4 B   4 200 250  225
# 5 B   5 300 350  325
# 6 C   6  10  20   15

# Example 2
df = data.frame(x=c("A","A","A","A","B","B","B","C"),
                low = c(-10,-5,-2,100,100,200,300,10),
                up = c(2,3,4,200,150,250,350,20), 
                val = c(1,2,3,150,125,225,325,15))

df %>% arrange(x,low) %>%
  group_by(x,set = cumsum(c(TRUE,x[-1] != x[-n()] | low[-1] > up[-n()]))) %>%
  summarize(low=min(low),up=max(up),val=lst(val)) %>%
  print.data.frame

#   x set low  up     val
# 1 A   1 -10   4 1, 2, 3
# 2 A   2 100 200     150
# 3 B   3 100 150     125
# 4 B   4 200 250     225
# 5 B   5 300 350     325
# 6 C   6  10  20      15