Выберите строки по дате в интервале в data.table - PullRequest
0 голосов
/ 26 июня 2018

Я хотел бы выбрать наблюдения в таблице данных, которые попадают в интервалы времени, указанные во второй таблице данных - интервалы - это периоды времени, когда наблюдения производятся одновременно с 2 платформ.

Первая таблица данных выглядит примерно так. Это куча наблюдений животных.

obs = data.table(sighting = as.POSIXct(c("2018-08-12 16:30:00", "2018-08-12 16:35:00", "2018-08-12 16:38:00", "2107-08-13 15:13:00", "2107-08-13 16:13:00", "2017-08-14 11:12:13"), format = "%Y-%m-%d %H:%M:%OS", tz = "America/Halifax"), encounter = c("1", "1", "1", "2", "3", "4"), what = c("frog", "frog", "toad", "bird", "goat","bird"))

Наблюдения проводились с 2 платформ.

platformA = data.table(station = "A", on.effort = as.POSIXct(c("2018-08-12 16:00:00", "2018-08-12 17:35:00","2017-08-14 11:00:13", "2018-08-15 17:35:00"), format = "%Y-%m-%d %H:%M:%OS", tz = "America/Halifax"), off.effort = as.POSIXct(c("2018-08-12 16:36:00", "2018-08-12 18:35:00","2017-08-14 12:12:13", "2018-08-15 18:35:00"), format = "%Y-%m-%d %H:%M:%OS", tz = "America/Halifax"))

platformB = data.table(station = "B", on.effort = as.POSIXct(c("2018-08-12 16:15:00", "2018-08-12 17:40:00", "2018-08-13 17:40:00","2017-08-14 11:05:13"), format = "%Y-%m-%d %H:%M:%OS", tz = "America/Halifax"), off.effort = as.POSIXct(c("2018-08-12 16:40:00", "2018-08-13 17:45:00", "2018-08-12 18:20:00","2017-08-14 12:30:13"), format = "%Y-%m-%d %H:%M:%OS", tz = "America/Halifax"))

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

setkey(platformA, on.effort, off.effort)
setkey(platformB, on.effort, off.effort)

common = foverlaps(platformA, platformB,type="any",nomatch=0)

common$x = intersect(interval(common$on.effort, common$off.effort), 
                     interval(common$i.on.effort, common$i.off.effort))

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

obs[, sighting2 := sighting]

Но foverlaps хочет, чтобы "начало" и "конец" каждого интервала были в отдельных столбцах, а это не то, как интервалы хранятся в общих $ x.

Я бы хотел, чтобы мой вывод выглядел следующим образом

           sighting encounter what
2018-08-12 16:30:00         1 frog
2018-08-12 16:35:00         1 frog
2017-08-14 11:12:13         4 bird

Буду признателен за любые советы. Возможно, я мог бы быть более эффективным раньше? Благодаря.

Ответы [ 2 ]

0 голосов
/ 26 июня 2018

Я думаю, что это должно работать, даже если у вас разные номера наблюдений между платформами. Используя данные obs, platformA и platformB, как указано выше, увеличьте или уменьшите интервалы для обеих платформ, как вы делали выше в common:

common = intersect(interval(platformA$on.effort, platformA$off.effort), 
                   interval(platformB$on.effort, platformB$off.effort))

Вы должны быть в состоянии использовать %within%, чтобы проверить, есть ли случаи, когда прицел попадает в общий интервал:

obs$both.seen <- sapply(obs$sighting, function(s){
  any(s %within% common)
})

OR

obs[, both.seen := sapply(sighting, function(x) any(x %within% common))]

Новый obs:

> obs
              sighting encounter what both.seen
1: 2018-08-12 16:30:00         1 frog      TRUE
2: 2018-08-12 16:35:00         1 frog      TRUE
3: 2018-08-12 16:38:00         1 toad     FALSE
4: 2107-08-13 15:13:00         2 bird     FALSE
5: 2107-08-13 16:13:00         3 goat     FALSE
6: 2017-08-14 11:12:13         4 bird      TRUE

Подмножество, чтобы получить желаемый результат:

obs <- obs[both.seen == 1][, both.seen := NULL][]

> obs
              sighting encounter what
1: 2018-08-12 16:30:00         1 frog
2: 2018-08-12 16:35:00         1 frog
3: 2017-08-14 11:12:13         4 bird
0 голосов
/ 26 июня 2018

Я верю это дает вам то, что вы хотите. Он не использует преимущества data.table функций и работает полностью на базе R. Я не уверен, приведет ли это к проблемам с производительностью ваших данных, но, возможно, это даст возможность подумать о более data.table -эски функции.

library(data.table)

# Set up the data
obs = data.table(sighting = as.POSIXct(c("2018-08-12 16:30:00", 
                                         "2018-08-12 16:35:00", 
                                         "2018-08-12 16:38:00", 
                                         "2107-08-13 15:13:00", 
                                         "2107-08-13 16:13:00", 
                                         "2017-08-14 11:12:13"), 
                                       format = "%Y-%m-%d %H:%M:%OS", 
                                       tz = "America/Halifax"), 
                 encounter = c("1", "1", "1", "2", "3", "4"), 
                 what = c("frog", "frog", "toad", "bird", "goat","bird"))

platformA = data.table(station = "A", 
                       on.effort = as.POSIXct(c("2018-08-12 16:00:00", 
                                                "2018-08-12 17:35:00",
                                                "2017-08-14 11:00:13"), 
                                              format = "%Y-%m-%d %H:%M:%OS", 
                                              tz = "America/Halifax"), 
                       off.effort = as.POSIXct(c("2018-08-12 16:36:00", 
                                                 "2018-08-12 18:35:00",
                                                 "2017-08-14 12:12:13"), 
                                               format = "%Y-%m-%d %H:%M:%OS", 
                                               tz = "America/Halifax"))

platformB = data.table(station = "B", 
                       on.effort = as.POSIXct(c("2018-08-12 16:15:00", 
                                                "2018-08-12 17:40:00",
                                                "2017-08-14 11:05:13"), 
                                              format = "%Y-%m-%d %H:%M:%OS", 
                                              tz = "America/Halifax"), 
                       off.effort = as.POSIXct(c("2018-08-12 16:40:00", 
                                                 "2018-08-12 18:20:00",
                                                 "2017-08-14 12:30:13"), 
                                               format = "%Y-%m-%d %H:%M:%OS", 
                                               tz = "America/Halifax"))

# Get the start and end times for each observation (note use of pmax and pmin)
starts = pmax(platformA$on.effort, platformB$on.effort)
ends = pmin(platformA$off.effort, platformB$off.effort)

# For each sighting in obs check if it falls in between any of the intervals
seen = sapply(obs$sighting, function(x) {    
    any(x >= starts & x <= ends)
})

# Subset the data
obs[seen, ]

              sighting encounter what
1: 2018-08-12 16:30:00         1 frog
2: 2018-08-12 16:35:00         1 frog
3: 2017-08-14 11:12:13         4 bird

Основным аспектом этого решения является присвоение start и end. Поскольку мы ищем пересечение времени наблюдения на двух платформах, наше время начала - это более позднее время двух (то есть максимум) и наше время окончания в самое раннее время двух платформ (то есть мин). Используя pmin и pmax, мы можем получить минимальное и максимальное значения соответственно для векторов времени. При выполнении сравнения в x >= start & x <= min единичное время x сравнивается поэлементно с парой start[i] и end[i], что дает нам наш интервал сравнения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...