I am looking to flag rows in my df that have overlapping ranges (looking to create the Overlap Column) based a range of numeric variables (Min,Max), which I could transform into integer if necessary:
Class    Min  Max
    A    100  200
    A    120  205
    A    210  310
    A    500  630
    A    510  530
    A    705  800
Transform into:
Class    Min  Max  Overlap
    A    100  200        1
    A    120  205        1
    A    210  310        0
    A    500  630        1
    A    510  530        1
    A    705  800        0
I have tried IRanges without much success - any ideas?
I find data.table very effective for doing overlaps, using foverlaps
 library(data.table)
Recreating the data:
dt <- data.table(Class = c("A", "A", "A", "A", "A", "A"),
           Min = c(100, 120, 210, 500, 510, 705),
           Max = c(200, 205, 310, 630, 530, 800))
Keying the data.table, this is required for the function:
setkey(dt, Min, Max)
here we do foverlaps against itself, then filter, removing those rows which are overlapping with themselves. The number of rows are then counted grouped by Min and Max.
dt_overlaps <- foverlaps(dt, dt, type = "any")[Min != i.Min & Max != i.Max, .(Class, Overlap = .N), by = c("Min", "Max")]
Thanks to DavidArenburg
dt[dt_overlaps, Overlap := 1]
Results:
> dt
  Class Min Max Overlap
1     A 100 200       1
2     A 120 205       1
3     A 210 310      NA
4     A 500 630       1
5     A 510 530       1
6     A 705 800      NA
There is probably neater data.table code for this, but I'm learning as well.
outer is my function of choice for doing pairwise comparisons fast. You can create the pairwise comparison of the interval endpoints using outer and then combine the comparisons in any way you want. In this case I check if the two rules required for an overlap hold true simultaneously.
library(dplyr)
df_foo = read.table(
textConnection("Class    Min  Max
A    100  200
A    120  205
A    210  310
A    500  630
A    510  530
A    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 
)
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With