使用R查找因素水平的重叠范围

3
我需要在单个数据集中查找重叠的范围,但需要为每个ID或因子级别找到它们。任何协助将不胜感激!
    library(dplyr)

df_foo = read.table(
  textConnection("Class    Min  Max
A    500  630
A    100  200
B    100  200
A    210  310
A    200  210
B    210  310
A    510  530
B    200  210
A    705  800
B    500  630
B    510  530
B    705  800"), header = TRUE
)

c = outer(df_foo$Max, df_foo$Min, ">")
d = outer(df_foo$Min, df_foo$Max, "<")

df_foo %>% 
  mutate(Overlap = apply(c & d, 1, sum) > 1 
  )

我得到的结果如下所示:
   Class Min Max Overlap
1      A 500 630    TRUE
2      A 100 200    TRUE
3      B 100 200    TRUE
4      A 210 310    TRUE
5      A 200 210    TRUE
6      B 210 310    TRUE
7      A 510 530    TRUE
8      B 200 210    TRUE
9      A 705 800    TRUE
10     B 500 630    TRUE
11     B 510 530    TRUE
12     B 705 800    TRUE

但我想要像这样找到A和B每个级别之间的重叠部分:

   Class Min Max Overlap
1      A 500 630    TRUE
2      A 100 200    FALSE
3      B 100 200    FALSE
4      A 210 310    FALSE
5      A 200 210    FALSE
6      B 210 310    FALSE
7      A 510 530    TRUE
8      B 200 210    FALSE
9      A 705 800    FALSE
10     B 500 630    TRUE
11     B 510 530    TRUE
12     B 705 800    FALSE
3个回答

2

我在data.table中有最初的回答,将其翻译成dplyr应该很简单。思路是创建每个类别的先前累积最大值的向量:

df_foo <- setDT(df_foo)
df_foo[, shiftedmaxmax := c(NA,cummax(Max)[1:(.N-1)]),by = Class  ]


    Class Min Max shiftedmaxmax
 1:     A 100 200            NA
 2:     A 200 210           200
 3:     A 210 310           210
 4:     A 500 630           310
 5:     A 510 530           630
 6:     A 705 800           630
 7:     B 100 200            NA
 8:     B 200 210           200
 9:     B 210 310           210
10:     B 500 630           310
11:     B 510 530           630
12:     B 705 800           630

将最小值与之前的最大值进行比较(如果小于此值,则当前行在上一行范围内)。

注:Maximum在此处翻译为“最大值”,Original Answer翻译成“最初的回答”。

df_foo[,superposed := Min < shiftedmaxmax]

    Class Min Max shiftedmaxmax superposed
 1:     A 100 200            NA         NA
 2:     A 200 210           200      FALSE
 3:     A 210 310           210      FALSE
 4:     A 500 630           310      FALSE
 5:     A 510 530           630       TRUE
 6:     A 705 800           630      FALSE
 7:     B 100 200            NA         NA
 8:     B 200 210           200      FALSE
 9:     B 210 310           210      FALSE
10:     B 500 630           310      FALSE
11:     B 510 530           630       TRUE
12:     B 705 800           630      FALSE

第一个叠加物缺失,可以通过以下方式获得:

Original Answer翻译成"最初的回答"

df_foo[,superposedsource :=  Max %in% shiftedmaxmax[superposed],by = Class]
df_foo[,superposedtot := ifelse((superposed | superposedsource) &,T,F)]

    Class Min Max shiftedmaxmax superposed superposedsource superposedtot
 1:     A 100 200            NA         NA            FALSE            NA
 2:     A 200 210           200      FALSE            FALSE         FALSE
 3:     A 210 310           210      FALSE            FALSE         FALSE
 4:     A 500 630           310      FALSE             TRUE          TRUE
 5:     A 510 530           630       TRUE            FALSE          TRUE
 6:     A 705 800           630      FALSE            FALSE         FALSE
 7:     B 100 200            NA         NA            FALSE            NA
 8:     B 200 210           200      FALSE            FALSE         FALSE
 9:     B 210 310           210      FALSE            FALSE         FALSE
10:     B 500 630           310      FALSE             TRUE          TRUE
11:     B 510 530           630       TRUE            FALSE          TRUE
12:     B 705 800           630      FALSE            FALSE         FALSE

谢谢,不幸的是这些范围并不是按升序或降序排列的。它们都混在一起了。我已经编辑了数据集以反映这一点。 - Marycee

1
使用 dplyr
df=df_foo%>%group_by(Class)%>%
  mutate(Overlap=if_else(Min<lag(Max,order_by=Class),TRUE,FALSE))
df$Overlap[which(df$Overlap==TRUE)-1]=TRUE
df$Overlap[which(is.na(df$Overlap))]=FALSE

> df
# A tibble: 12 x 4
# Groups:   Class [2]
   Class   Min   Max Overlap
   <fct> <dbl> <dbl> <lgl>  
 1 A       100   200 FALSE  
 2 A       200   210 FALSE  
 3 A       210   310 FALSE  
 4 A       500   630 TRUE   
 5 A       510   530 TRUE   
 6 A       705   800 FALSE  
 7 B       100   200 FALSE  
 8 B       200   210 FALSE  
 9 B       210   310 FALSE  
10 B       500   630 TRUE   
11 B       510   530 TRUE   
12 B       705   800 FALSE 

这段代码假设你的值是按升序排列的,因为它只与上一行进行比较。
编辑 不是最漂亮的但有效。
df_foo$Class=as.character.factor(df_foo$Class)
df_foo=as.data.frame(df_foo)
df_foo$Overlap=rep("FALSE",nrow(df_foo))
for (i in 1:nrow(df_foo)){
  aux=FALSE
  class=df_foo$Class[i]
  df=df_foo[-i,]%>%filter(.,Class==class)
  for (j in 1:nrow(df)){
    if (df_foo[i,"Min"]<df[j,"Max"] & df_foo[i,"Max"] > df[j,"Min"]){
      aux=TRUE
    }
  }
  df_foo[i,"Overlap"]=aux
}


> df_foo
   Class Min Max Overlap
1      A 500 630    TRUE
2      A 100 200   FALSE
3      B 100 200   FALSE
4      A 210 310   FALSE
5      A 200 210   FALSE
6      B 210 310   FALSE
7      A 510 530    TRUE
8      B 200 210   FALSE
9      A 705 800   FALSE
10     B 500 630    TRUE
11     B 510 530    TRUE
12     B 705 800   FALSE

我希望能够使用 dplyr 完成此操作,但我无法理解。它会循环遍历 df_foo 的每一行;使用同一组的所有其他行生成一个 dataframe,并比较是否存在重叠(min<maxmax<min


谢谢,我应该表述得更清楚,但在我的实际数据集中,所有值都混杂在一起,不遵循升序或降序。 - Marycee
是否可能存在多个重叠部分?如果不行,只需按“Class”升序重新排列代码即可。如果可以存在多个重叠部分,则应明确更改。 - boski
可能会有多个重叠。我已经编辑了示例以显示数据如何混合。感谢您的帮助! - Marycee

1

另一种data.table方法。
在这个答案中,样本数据/范围的顺序并不重要... foverlaps()会为您完成所有繁重的工作。

样本数据

library( data.table )
dt <- as.data.table( df_foo )

代码

#set key for the data.table
setkey(dt, Min, Max)
#perform overlap join, keep only joined ranges where the class is the same, and Min and Max are not the same.
result <- foverlaps( dt, dt )[ Class == i.Class & !(Min == i.Min | Max == i.Max | Min == i.Max | Max == i.Min), ]
#create a logical vector (i.e. Overlap) by checking if the (pasted) combination of
#Class, Min and Max exists in both 'dt' and 'result'
dt[ , Overlap := paste0( Class, Min, Max ) %in% paste0( result$Class, result$Min, result$Max) ][]

#     Class Min Max Overlap
#  1:     A 100 200   FALSE
#  2:     B 100 200   FALSE
#  3:     A 200 210   FALSE
#  4:     B 200 210   FALSE
#  5:     A 210 310   FALSE
#  6:     B 210 310   FALSE
#  7:     A 500 630    TRUE
#  8:     B 500 630    TRUE
#  9:     A 510 530    TRUE
# 10:     B 510 530    TRUE
# 11:     A 705 800   FALSE
# 12:     B 705 800   FALSE

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接