Вот хороший способ сделать это с пакетом plyr
и рекурсивной функцией:
library(plyr)
splitTimes <- function(arow, df) {
overlap_all = arow$start > df[, 'start'] & arow$end < df[, 'end']
overlap_middle = arow$start < df[, 'start'] & arow$end > df[, 'end']
overlap_end = arow$start < df[, 'start'] & arow$end > df[, 'start'] & arow$end < df[, 'end']
overlap_start = arow$start > df[, 'start'] & arow$end > df[, 'end'] & arow$start < df[, 'end']
if(any(overlap_all)) {
data.frame()
} else if(any(overlap_middle)) {
outrows = rbind(data.frame(start=arow$start, end=df[overlap_middle, 'start'][1]-1, sp=arow$sp),
data.frame(start=df[overlap_middle, 'end'][1]+1, end=arow$end, sp=arow$sp))
ddply(outrows, 'start', 'splitTimes', df)
} else if(any(overlap_end)) {
data.frame(start=arow$start, end=df[overlap_end, 'start']-1, sp=arow$sp)
} else if(any(overlap_start)) {
data.frame(start=df[overlap_start, 'end']+1, end=arow$end, sp=arow$sp)
} else {
arow
}
}
Тогда вы можете сделать:
> dfall = read.table('data.txt', header=T, colClasses=c('POSIXct', 'POSIXct', 'factor'))
> dfAB = subset(dfall, sp %in% c('A', 'B'))
> dfC = subset(dfall, sp == 'C')
> arrange(rbind(ddply(dfAB, 'start', 'splitTimes', dfC), dfC), start)
start end sp
1 2010-06-01 17:00:00 2010-06-01 19:30:00 A
2 2010-06-01 19:30:01 2010-06-01 19:44:59 B
3 2010-06-01 19:45:00 2010-06-01 19:55:00 C
4 2010-06-01 19:55:01 2010-06-01 20:00:00 B
5 2010-06-01 20:00:01 2010-06-01 20:04:59 A
6 2010-06-01 20:05:00 2010-06-01 20:10:00 C
7 2010-06-01 20:10:01 2010-06-01 20:11:59 A
8 2010-06-01 20:12:00 2010-06-01 20:15:00 C
9 2010-06-01 20:15:01 2010-06-01 20:30:00 A
10 2010-06-01 20:30:01 2010-06-01 20:34:59 B
11 2010-06-01 20:35:00 2010-06-01 20:40:10 C
12 2010-06-01 20:40:11 2010-06-01 20:50:00 A
, которая дает вам именно то, что выwant.
В других случаях могут быть небольшие ошибки, поскольку ваш пример данных не охватывает их все, но это, по крайней мере, общая идея.Надеюсь, поможет.Удачи!