Удалите строки, которые ближе друг к другу, чем определенное время, и добавьте информацию об удаленных строках в двух новых столбцах. - PullRequest
0 голосов
/ 16 апреля 2019

У меня есть датафрейм df1, который суммирует обнаружения различных животных с течением времени. Столбец Rec указывает, какое устройство его обнаружило (V4, V6 и т. Д.), А столбец Ind указывает человека.

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

Кроме того, я хочу создать следующие столбцы:

1) Num_Rec: Суммируется, как ДРУГОЕ Rec обнаружило животное в указанном интервале 55 с.

2) Which_Rec: в нем обобщено название ДРУГОГО Rec, обнаружившего животное в указанном интервале 55 с.

Если в интервале 55 с одно и то же животное дважды поймано одним и тем же Rec (т. Е. Строки 12 и 13 в df1), я считаю 2-й ряд (= обнаружение) ошибкой (не возможно, что один и тот же приемник дважды ловит одного и того же животного за 55 с), и я не принимаю во внимание этот ряд в столбцах Num_Rec и Which_Rec (т. е. в Result я не считаю df1$Datetime[13] ни в Result$Num_Rec[11], ни в Result$Which_Rec[11]).

Как пример:

df1<-data.frame(DateTime=c("2016-08-01 12:04:07","2016-08-01 12:06:07","2016-08-01 12:06:58","2016-08-01 13:12:12","2016-08-01 14:04:07","2016-08-01 13:12:45","2016-08-01 15:04:07","2016-08-01 17:13:16","2016-08-01 17:21:16","2016-08-01 17:21:34","2016-08-01 17:23:42","2016-08-01 17:27:16","2016-08-01 17:27:22","2016-08-01 17:28:01","2016-08-01 17:29:28","2016-08-01 17:28:08"),Rec=c("V6", "V7", "V6", "V6", "V7", "V7", "V6", "V7", "V7","V7","V6","V6", "V6", "V9", "V7", "V4"),Ind=c(16, 17, 16, 16, 17, 16, 17, 16, 17, 16, 16, 17, 17, 17, 16, 17))
df1$DateTime<- as.POSIXct(df1$DateTime, format= "%Y-%m-%d %H:%M:%S", tz= "UTC")

df1
              DateTime      Rec         Ind
1  2016-08-01 12:04:07       V6          16
2  2016-08-01 12:06:07       V7          17
3  2016-08-01 12:06:58       V6          16
4  2016-08-01 13:12:12       V6          16
5  2016-08-01 14:04:07       V7          17
6  2016-08-01 13:12:45       V7          16
7  2016-08-01 15:04:07       V6          17
8  2016-08-01 17:13:16       V7          16
9  2016-08-01 17:21:16       V7          17
10 2016-08-01 17:21:34       V7          16
11 2016-08-01 17:23:42       V6          16
12 2016-08-01 17:27:16       V6          17 
13 2016-08-01 17:27:22       V6          17
14 2016-08-01 17:28:01       V9          17 
15 2016-08-01 17:29:28       V7          16
16 2016-08-01 17:28:08       V4          17 

То, что я хочу получить, это:

Result
              DateTime      Rec         Ind Num_Rec Which_Rec
1  2016-08-01 12:04:07       V6          16       0        NA
2  2016-08-01 12:06:07       V7          17       0        NA
3  2016-08-01 12:06:58       V6          16       0        NA
4  2016-08-01 13:12:12       V6          16       1        V7 
5  2016-08-01 14:04:07       V7          17       0        NA
6  2016-08-01 15:04:07       V6          17       0        NA
7  2016-08-01 17:13:16       V7          16       0        NA
8  2016-08-01 17:21:16       V7          17       0        NA
9  2016-08-01 17:21:34       V7          16       0        NA
10 2016-08-01 17:23:42       V6          16       0        NA
11 2016-08-01 17:27:16       V6          17       2     V9 V4 
12 2016-08-01 17:29:28       V7          16       0        NA

Note1: In `Result[4,]` there is a detection of the individual `16` at 13:12:12 and in an interval of 55s there is another detection (indicated in `Num_Rec`) in the `Rec` number `V7` (indicated in `Which_Rec`).

Note2: In `Result[11,]` there is one detection of the individual `17` at 17:27:16 in `Rec` `V6`, and after that, in an interval of  55s, there are two more TRUE detections, as it is indicated in `Num_Rec` with a `2`. In `Which_Rec` we specify the name of the receivers. In this case:`V9` and `V4`. We have also a FALSE detection in this interval of 55s that starts at 17:27:16. It is in row 13 in `df1` (It is a false detection because an animal can't be detected twice for the same `Rec` in 55s).

Я хотел бы знать, как это сделать с большим кадром данных. Я думаю, это возможно с пакетом dplyr, но я не знаю, как.

Я попробовал это, как предложил коллега из StackOverflow в ответах:

    library(tidyverse)

    df <- data.frame(DateTime=c("2016-08-01 12:04:07","2016-08-01 12:06:07","2016-08-01 12:06:58","2016-08-01 13:12:12","2016-08-01 14:04:07","2016-08-01 13:12:45","2016-08-01 15:04:07","2016-08-01 17:13:16","2016-08-01 17:21:16","2016-08-01 17:21:34","2016-08-01 17:23:42","2016-08-01 17:27:16","2016-08-01 17:27:22","2016-08-01 17:28:01","2016-08-01 17:29:28","2016-08-01 17:28:08"),Rec=c("V6", "V7", "V6", "V6", "V7", "V7", "V6", "V7", "V7","V7","V6","V6", "V6", "V9", "V7", "V4"),Ind=c(16, 17, 16, 16, 17, 16, 17, 16, 17, 16, 16, 17, 17, 17, 16, 17))%>%
      mutate(Rec = as.character(Rec),
             DateTime = as.POSIXct(as.character(DateTime))) %>% 
      as_tibble()

First I define a delete_flag by checking if the same individual has been caught more than  once within 55 seconds. Then I filter the data accordingly.
Next I use `pmap` to get `Num_Rec` and `Which_Rec`:

    df %>% 
      mutate(delete_flag = map2_lgl(DateTime, Ind, ~filter(df, DateTime < .x, DateTime >= .x - 55, 
                                                           Ind == .y) %>% nrow %>% as.logical())) %>% 
      filter(!delete_flag) %>%
      select(-delete_flag) %>% 
      mutate(x = pmap(list(DateTime, Rec, Ind), ~filter(df, DateTime > ..1, DateTime <= ..1 +55,
                                             Rec != ..2, Ind == ..3) %>% 
                        summarise(Num_Rec = n(),
                                  Which_Rec = paste0(Rec, collapse = " ")))) %>% 
      unnest()

       DateTime            Rec     Ind Num_Rec Which_Rec
       <dttm>              <chr> <dbl>   <int> <chr>    
     1 2016-08-01 12:04:07 V6       16       0 ""       
     2 2016-08-01 12:06:07 V7       17       0 ""       
     3 2016-08-01 12:06:58 V6       16       0 ""       
     4 2016-08-01 13:12:12 V6       16       1 V7       
     5 2016-08-01 14:04:07 V7       17       0 ""       
     6 2016-08-01 15:04:07 V6       17       0 ""       
     7 2016-08-01 17:13:16 V7       16       0 ""       
     8 2016-08-01 17:21:16 V7       17       0 ""       
     9 2016-08-01 17:21:34 V7       16       0 ""       
    10 2016-08-01 17:23:42 V6       16       0 ""       
    11 2016-08-01 17:27:16 V6       17       2 V9 V4    
    12 2016-08-01 17:29:28 V7       16       0 "" 

Но то, что я получаю, применяя код, который вы видите выше, отличается от того, что он получает, я не знаю почему:

# A tibble: 12 x 5
   DateTime            Rec     Ind Num_Rec Which_Rec
   <dttm>              <chr> <dbl>   <int> <chr>    
 1 2016-08-01 12:04:07 V6       16      12 ""       
 2 2016-08-01 12:06:07 V7       17      12 ""       
 3 2016-08-01 12:06:58 V6       16      12 ""       
 4 2016-08-01 13:12:12 V6       16      12 V7       
 5 2016-08-01 14:04:07 V7       17      12 ""       
 6 2016-08-01 15:04:07 V6       17      12 ""       
 7 2016-08-01 17:13:16 V7       16      12 ""       
 8 2016-08-01 17:21:16 V7       17      12 ""       
 9 2016-08-01 17:21:34 V7       16      12 ""       
10 2016-08-01 17:23:42 V6       16      12 ""       
11 2016-08-01 17:27:16 V6       17      12 V9 V4    
12 2016-08-01 17:29:28 V7       16      12 ""       

1 Ответ

2 голосов
/ 16 апреля 2019

вот возможное решение, использующее map2 и pmap из пакета purrr.

Во-первых, вот данные, с которыми я работаю:

library(tidyverse)

df <- data.frame(DateTime=c("2016-08-01 12:04:07","2016-08-01 12:06:07","2016-08-01 12:06:58","2016-08-01 13:12:12","2016-08-01 14:04:07","2016-08-01 13:12:45","2016-08-01 15:04:07","2016-08-01 17:13:16","2016-08-01 17:21:16","2016-08-01 17:21:34","2016-08-01 17:23:42","2016-08-01 17:27:16","2016-08-01 17:27:22","2016-08-01 17:28:01","2016-08-01 17:29:28","2016-08-01 17:28:08"),Rec=c("V6", "V7", "V6", "V6", "V7", "V7", "V6", "V7", "V7","V7","V6","V6", "V6", "V9", "V7", "V4"),Ind=c(16, 17, 16, 16, 17, 16, 17, 16, 17, 16, 16, 17, 17, 17, 16, 17))%>%
  mutate(Rec = as.character(Rec),
         DateTime = as.POSIXct(as.character(DateTime))) %>% 
  as_tibble()

СначалаЯ определяю delete_flag, проверяя, был ли один и тот же человек пойман более одного раза в течение 55 секунд.Затем я фильтрую данные соответственно.Затем я использую pmap, чтобы получить Num_Rec и Which_Rec:

df %>% 
  mutate(delete_flag = map2_lgl(DateTime, Ind, ~filter(df, DateTime < .x, DateTime >= .x - 55, 
                                                       Ind == .y) %>% nrow %>% as.logical())) %>% 
  filter(!delete_flag) %>%
  select(-delete_flag) %>% 
  mutate(x = pmap(list(DateTime, Rec, Ind), ~filter(df, DateTime > ..1, DateTime <= ..1 +55,
                                         Rec != ..2, Ind == ..3) %>% 
                    summarise(Num_Rec = n(),
                              Which_Rec = paste0(Rec, collapse = " ")))) %>% 
  unnest()

   DateTime            Rec     Ind Num_Rec Which_Rec
   <dttm>              <chr> <dbl>   <int> <chr>    
 1 2016-08-01 12:04:07 V6       16       0 ""       
 2 2016-08-01 12:06:07 V7       17       0 ""       
 3 2016-08-01 12:06:58 V6       16       0 ""       
 4 2016-08-01 13:12:12 V6       16       1 V7       
 5 2016-08-01 14:04:07 V7       17       0 ""       
 6 2016-08-01 15:04:07 V6       17       0 ""       
 7 2016-08-01 17:13:16 V7       16       0 ""       
 8 2016-08-01 17:21:16 V7       17       0 ""       
 9 2016-08-01 17:21:34 V7       16       0 ""       
10 2016-08-01 17:23:42 V6       16       0 ""       
11 2016-08-01 17:27:16 V6       17       2 V9 V4    
12 2016-08-01 17:29:28 V7       16       0 "" 
...