如何 return R 中两个数据帧之间共享的值范围?

How to return the range of values shared between two data frames in R?

我有几个具有相同列名的数据框,ID ,以下是范围的开始 from 和结束 to 以及每个范围的 group 标签。

我想要的是找出data frames其中一个的fromto的哪些值包含在另一个的范围内。我留下一个示例图片来说明我想要实现的目标(暂时不需要图表)

我以为我可以使用 dplyr packagebetween() 来完成此操作,但不行。这可以通过使用 if between() returns true then return the maximum value of from and the minimum value of to between the data frames.

我留下示例数据框和results我愿意获得。

a <- data.frame(ID = c(1,1,1,2,2,2,3,3,3),from=c(1,500,1000,1,500,1000,1,500,1000),
                to=c(400,900,1400,400,900,1400,400,900,1400),group=rep("a",9))
b <- data.frame(ID = c(1,1,1,2,2,2,3,3,3),from=c(300,1200,1900,1400,2800,3700,1300,2500,3500),
                to=c(500,1500,2000,2500,3000,3900,1400,2800,3900),group=rep("b",9))
results <- data.frame(ID = c(1,1,1,2,3),from=c(300,500,1200,1400,1300),
                      to=c(400,500,1400,1400,1400),group=rep("a, b",5))

我尝试使用这个函数,它会 return 匹配时的值,但它不会 return 它们之间共享的范围

f <- function(vec, id) {
  if(length(.x <- which(vec >= a$from & vec <= a$to & id == a$ID))) .x else NA
}
b$fromA <- a$from[mapply(f, b$from, b$ID)]
b$toA <- a$to[mapply(f, b$to, b$ID)]

我们可以假设起点和终点在不同的列中,并且同一组(a 和 b)的范围不重叠。这是我的解决方案。为了清楚起见,我已将 'point_1' 和 'point_2' 称为您的变异 'from' 和 'to'。

可以绑定两个dataframes,将from col与之前的值lag(from)进行比较,看实际值是否更小。您还将之前的 lag(to) 与实际的 to col 进行比较,以查看范围的最大值是否与之前的范围重叠。

重要的是,这些操作不会区分它们比较的两行是否来自同一组(a 或 b)。因此,过滤 point_1(新的突变 'from' 列)中的 NA,您将删除错误的突变值。 另请注意,我假设 'a' 中的范围不能与 'b' 中的两行重叠。在你的 'results' table 中没有发生,但你应该在你的数据框中检查。

res = rbind(a,b) %>%  # Bind by rows
  arrange(ID,from) %>% # arrange by ID and starting point (from)
  group_by(ID) %>% # perform the following operations grouped by IDs
# Here is the trick. If the ranges for the same ID and group (i.e. 1,a) do   
# not overlap, when you mutate the following cols the result will be NA for 
# point_1.
  mutate(point_1 = ifelse(from <= lag(to), from, NA),
         point_2 = ifelse(lag(to)>=to, to, lag(to)),
         groups = paste(lag(group), group, sep = ',')) %>% 
  filter(! is.na(point_1)) %>%  # remove NAs in from
  select(ID,point_1, point_2, groups)  # get the result dataframe

如果您尝试一下代码,而不是使用 filter()select(),您就会明白它是如何工作的。

> res
# A tibble: 5 x 4
# Groups:   ID [3]
     ID point_1 point_2 groups
  <dbl>   <dbl>   <dbl> <chr> 
1     1     300     400 a,b   
2     1     500     500 b,a   
3     1    1200    1400 a,b   
4     2    1400    1400 a,b   
5     3    1300    1400 a,b