Сравнить интервалы дат в одном и том же фрейме данных - PullRequest
0 голосов
/ 25 апреля 2018

У меня есть поиск и поиск похожих вопросов, но я могу заставить его работать с моими данными.

У меня есть фрейм данных с датами начала и окончания, а также рядом других факторов.В идеале, дата начала строки должна быть позади даты окончания любой предыдущей строки, но данные дублируются, начинаются или заканчиваются, и иногда интервал дат перекрывается.

Я попытался создать воспроизводимый пример:

df = data.frame(start=c("2018/04/15 9:00:00","2018/04/15 9:00:00","2018/04/16 10:20:00","2018/04/16 15:30:00",
                   "2018/04/17 12:40:00","2018/04/17 18:50:00"),
                end=c("2018/04/16 8:00:00","2018/04/16 7:10:00","2018/04/17 18:20:00","2018/04/16 16:30:00",
                   "2018/04/17 16:40:00","2018/04/17 19:50:00"),
                value=c(10,15,11,13,14,12))

Мне удалось удалить дубликаты (даты окончания или начала), но я не могу удалить перекрывающиеся интервалы.Я хочу создать цикл, который «очищает» интервалы, содержащиеся в любом большем интервале.Таким образом, результаты выглядят так:

result = df[c(1,3,6),]

Я думал, что мог бы создать цикл, который "очистил бы" как дубликаты, так и перекрывающиеся интервалы, но я не могу заставить его работать.

Любойпредложения?

Ответы [ 2 ]

0 голосов
/ 25 апреля 2018

Альтернативный подход заключается в использовании %within% пакета lubridate():

library(lubridate)
# transform characters to dates
start_time <- as_datetime(df[ , "start"], tz = "UTC")
end_time <- as_datetime(df[ , "end"], tz = "UTC")
# construct intervals
start_end_intrvls <- interval(start_time, end_time)
# find indices of the non-within intervals
not_within <- !(sapply(FUN = function(i) any(start_end_intrvls[i] %within% start_end_intrvls[-i]), 
    X = seq(along.with = df[ , "start"])))
df[not_within, ]
#                 start                 end value
# 1  2018/04/15 9:00:00  2018/04/16 8:00:00    10
# 3 2018/04/16 10:20:00 2018/04/17 18:20:00    11
# 6 2018/04/17 18:50:00 2018/04/17 19:50:00    12

Обновление

Функция as_datetime() вызывает ошибку при применении к таблице:

as_datetime(tibble("2018/04/15 9:00:00"), tz = "UTC")
Error in as.POSIXct.default(x) : 
  do not know how to convert 'x' to class “POSIXct”

Приведенное выше решение может быть изменено для решения этой проблемы с заменой as_datetime() на as.POSIXlt():

df_tibble <- tibble(start=c("2018/04/15 9:00:00","2018/04/15 9:00:00","2018/04/16 10:20:00",
    "2018/04/16 15:30:00", "2018/04/17 12:40:00","2018/04/17 18:50:00"),
     end=c("2018/04/16 8:00:00","2018/04/16 7:10:00","2018/04/17 18:20:00","2018/04/16 16:30:00",
     "2018/04/17 16:40:00","2018/04/17 19:50:00"), value=c(10,15,11,13,14,12))

start_time_lst <- lapply(FUN = function(i) as.POSIXlt(as.character(df_tibble[i , "start"]),
    tz = "UTC"),
    X = seq(along.with = unlist(df_tibble[ , "start"])))
end_time_lst <- lapply(FUN = function(i) as.POSIXlt(as.character(df_tibble[ i, "end"]),
    tz = "UTC"),
    X = seq(along.with = unlist(df_tibble[ , "end"])))
start_end_intrvls <- lapply(function(i) interval(start_time_lst[[i]] , end_time_lst[[i]]), 
    X = seq(along.with = unlist(df_tibble[ , "start"])))
not_within <- sapply(function(i) !(any(unlist(Map(`%within%`, 
    start_end_intrvls[[i]], start_end_intrvls[-i])))), 
    X = seq(along.with = unlist(df_tibble[ , "start"])))
0 голосов
/ 25 апреля 2018

Пакет data.table подходит для такого рода проблем, используя перекрывающуюся функцию соединения foverlaps (созданную на основе функции findOverlaps из пакета Bioconductor IRanges) и затем анти-объединение (синтаксис data.table равен B[!A, on]).удалить эти внутренние интервалы.

library(data.table)
cols <- c("start", "end")
setDT(df)
df[, (cols) := lapply(.SD, function(x) as.POSIXct(x, format="%Y/%m/%d %H:%M:%S")), .SDcols=cols]
setkeyv(df, cols)
anti <- foverlaps(df, df, type="within")[start!=i.start | end!=i.end | value!=i.value]
df[!anti, on=.(start=i.start, end=i.end, value=i.value)]

#                  start                 end value
# 1: 2018-04-15 09:00:00 2018-04-16 08:00:00    10
# 2: 2018-04-16 10:20:00 2018-04-17 18:20:00    11
# 3: 2018-04-17 18:50:00 2018-04-17 19:50:00    12
...