如何从重复值中删除重叠的范围并保留关联值?
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
我有一个数据框,其中有一些重复的 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