Devo controllare le osservazioni degli uccelli fatte su un periodo più lungo per voci duplicate / sovrapposte.
Osservatori di diversi punti (A, B, C) hanno fatto osservazioni e li hanno contrassegnati su mappe cartacee. Quelle linee sono state portate in una linea con dati aggiuntivi per la specie, il punto di osservazione e gli intervalli di tempo in cui sono stati visti.
Normalmente, gli osservatori comunicano tra loro via telefono mentre osservano, ma a volte dimenticano, quindi ottengo quelle linee duplicate.
Ho già ridotto i dati a quelle linee che toccano il cerchio, quindi non devo fare un'analisi spaziale, ma solo confrontare gli intervalli di tempo per ogni specie e posso essere abbastanza sicuro che sia lo stesso individuo che si trova nel confronto .
Ora sto cercando un modo in R per identificare quelle voci che:
- sono realizzati lo stesso giorno con un intervallo di sovrapposizione
- e dove si trova la stessa specie
- e che sono stati fatti da diversi punti di osservazione (A o B o C o ...))
In questo esempio, ho trovato manualmente possibili voci duplicate della stessa persona. Il punto di osservazione è diverso (A <-> B), la specie è la stessa (Sst) e l'intervallo dei tempi di inizio e fine si sovrappone.
Vorrei ora creare un nuovo campo "duplicato" nel mio data.frame, dando a entrambe le righe un ID comune per poterle esportare e in seguito decidere cosa fare.
Ho cercato molte soluzioni già disponibili, ma non ho trovato nulla riguardo al fatto che devo sottoinsieme il processo per la specie (preferibilmente senza un anello) e devo confrontare le righe per 2 + x punti di osservazione.
Alcuni dati con cui giocare:
testdata <- structure(list(bird_id = c("20150712_0810_1410_A_1", "20150712_0810_1410_A_2",
"20150712_0810_1410_A_4", "20150712_0810_1410_A_7", "20150727_1115_1430_C_1",
"20150727_1120_1430_B_1", "20150727_1120_1430_B_2", "20150727_1120_1430_B_3",
"20150727_1120_1430_B_4", "20150727_1120_1430_B_5", "20150727_1130_1430_A_2",
"20150727_1130_1430_A_4", "20150727_1130_1430_A_5", "20150812_0900_1225_B_3",
"20150812_0900_1225_B_6", "20150812_0900_1225_B_7", "20150812_0907_1208_A_2",
"20150812_0907_1208_A_3", "20150812_0907_1208_A_5", "20150812_0907_1208_A_6"
), obsPoint = c("A", "A", "A", "A", "C", "B", "B", "B", "B",
"B", "A", "A", "A", "B", "B", "B", "A", "A", "A", "A"), species = structure(c(11L,
11L, 11L, 11L, 10L, 11L, 10L, 11L, 11L, 11L, 11L, 10L, 11L, 11L,
11L, 11L, 11L, 11L, 11L, 11L), .Label = c("Bf", "Fia", "Grr",
"Kch", "Ko", "Lm", "Rm", "Row", "Sea", "Sst", "Wsb"), class = "factor"),
from = structure(c(1436687150, 1436689710, 1436691420, 1436694850,
1437992160, 1437991500, 1437995580, 1437992360, 1437995960,
1437998360, 1437992100, 1437994000, 1437995340, 1439366410,
1439369600, 1439374980, 1439367240, 1439367540, 1439369760,
1439370720), class = c("POSIXct", "POSIXt"), tzone = ""),
to = structure(c(1436687690, 1436690230, 1436691690, 1436694970,
1437992320, 1437992200, 1437995600, 1437992400, 1437996070,
1437998750, 1437992230, 1437994220, 1437996780, 1439366570,
1439370070, 1439375070, 1439367410, 1439367820, 1439369930,
1439370830), class = c("POSIXct", "POSIXt"), tzone = "")), .Names = c("bird_id",
"obsPoint", "species", "from", "to"), row.names = c("20150712_0810_1410_A_1",
"20150712_0810_1410_A_2", "20150712_0810_1410_A_4", "20150712_0810_1410_A_7",
"20150727_1115_1430_C_1", "20150727_1120_1430_B_1", "20150727_1120_1430_B_2",
"20150727_1120_1430_B_3", "20150727_1120_1430_B_4", "20150727_1120_1430_B_5",
"20150727_1130_1430_A_2", "20150727_1130_1430_A_4", "20150727_1130_1430_A_5",
"20150812_0900_1225_B_3", "20150812_0900_1225_B_6", "20150812_0900_1225_B_7",
"20150812_0907_1208_A_2", "20150812_0907_1208_A_3", "20150812_0907_1208_A_5",
"20150812_0907_1208_A_6"), class = "data.frame")
Ho trovato una soluzione parziale con la funzione data.table foverlaps menzionata ad esempio qui https://stackoverflow.com/q/25815032
library(data.table)
#Subsetting the data for each observation point and converting them into data.tables
A <- setDT(testdata[testdata$obsPoint=="A",])
B <- setDT(testdata[testdata$obsPoint=="B",])
C <- setDT(testdata[testdata$obsPoint=="C",])
#Set a key for these subsets (whatever key exactly means. Don't care as long as it works ;) )
setkey(A,species,from,to)
setkey(B,species,from,to)
setkey(C,species,from,to)
#Generate the match results for each obsPoint/species combination with an overlapping interval
matchesAB <- foverlaps(A,B,type="within",nomatch=0L) #nomatch=0L -> remove NA
matchesAC <- foverlaps(A,C,type="within",nomatch=0L)
matchesBC <- foverlaps(B,C,type="within",nomatch=0L)
Certo, questo in qualche modo "funziona", ma non è davvero quello che mi piace ottenere alla fine.
Innanzitutto, devo codificare i punti di osservazione. Preferirei trovare una soluzione prendendo un numero arbitrario di punti.
In secondo luogo, il risultato non è in un formato in cui posso davvero riprendere a lavorare facilmente. Le righe corrispondenti vengono effettivamente inserite nella stessa riga, mentre il mio obiettivo è quello di inserire le righe sottostanti e, in una nuova colonna, avrebbero un identificatore comune.
In terzo luogo, devo verificare di nuovo manualmente, se un intervallo si sovrappone da tutti e tre i punti (che non è il caso dei miei dati, ma generalmente potrebbe)
Alla fine, vorrei solo ricevere un nuovo data.frame con tutti i candidati identificabili da un ID di gruppo che posso unire nuovamente alle righe ed esportare il risultato come layer per un ulteriore esame.
Qualcuno ha più idee su come farlo?
for
loop!