Фильтр R фрейм данных, зависящий от значений нескольких столбцов и вычисления даты и времени

#r #dataframe #datetime #camera

#r #фрейм данных #дата и время #камера

Вопрос:

У меня есть фрейм данных обнаружения фотоловушек с более чем 50 000 строк, и я хотел бы идентифицировать и / или удалить наблюдения одного вида, которые происходят в течение определенного периода времени другого вида на той же станции камеры.

Ниже приведен пример моего фрейма данных:

    Species    StationID    DateTime
1  Human      A            2013-05-20 10:00:00
2  Dog        A            2013-05-20 10:09:00
3  Dog        A            2013-05-21 10:40:00
4  Puma       B            2013-05-21 15:59:00
5  Dog        B            2013-05-23 10:05:00
6  Human      B            2013-05-23 10:10:00
  

Если бы я хотел идентифицировать / удалить все обнаружения собак в течение 10 минут по обе стороны от обнаружения человека на одной и той же станции камеры, я бы ожидал, что будут возвращены следующие данные:

    Species    StationID    DateTime
1  Human      A            2013-05-20 10:00:00
2  Dog        A            2013-05-21 10:40:00
3  Puma       B            2013-05-21 15:59:00
4  Human      B            2013-05-23 10:10:00
  

Среди прочего, я попытался разделить обнаружения людей и собак на отдельные фреймы данных и создать верхние и нижние столбцы даты и времени для наблюдений за собаками на основе желаемого временного допуска или -10 минут. Затем я использовал fuzzy_left_join, как показано ниже, который хорошо работал для обработки StationID, но он не возвращал правильные определения на основе указанных операций DateTime.

 Dog_HumanDF <- fuzzy_left_join(DogDF, HumanDF, 
                                  by = c("StationID" = "StationID",
                                         "DateTimeDogLower" = "DateTimeHuman", 
                                         "DateTimeDogUpper" = "DateTimeHuman"),  
                                  match_fun = list(`==`, `<=` , `>=`))
  

Я много искал похожие проблемы и решения, но не смог найти ничего, что соответствовало бы моим целям. Я бы предпочел решение, которое не требовало создания отдельных фреймов данных, как это было для fuzzy_join . Любая помощь очень ценится!

Ответ №1:

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

 no_bad_dogs <- function(df){
output <- list()
for(i in 1:length(unique(df$StationID))){
stat_df <- df[df$StationID==unique(df$StationID)[i],]
if("Human" %in% stat_df$Species amp; "Dog" %in% stat_df$Species){
HumanDF <- stat_df[stat_df$Species == "Human",]
dog_index <- which(stat_df$Species=="Dog")
DogDF <- stat_df[dog_index,]
bad_in_dog_index <- sapply(DogDF$DateTime, FUN = function(x, human_times){return(any( x >= human_times-600 amp; x <= human_times 600))},human_times = HumanDF$DateTime)
if(any(bad_in_dog_index)){
output[[i]] <- stat_df[-dog_index[bad_in_dog_index],]} else {output[[i]] <- stat_df }
} else { output[[i]] <- stat_df }
}
do.call("rbind", output)
}