Tengo que verificar las observaciones de aves realizadas durante un período más largo para entradas duplicadas / superpuestas.
Los observadores de diferentes puntos (A, B, C) hicieron observaciones y las marcaron en mapas de papel. Esas líneas se incorporaron a una característica de línea con datos adicionales para la especie, el punto de observación y los intervalos de tiempo en que se vieron.
Normalmente, los observadores se comunican entre sí por teléfono mientras observan, pero a veces se olvidan, así que obtengo esas líneas duplicadas.
Ya reduje los datos a esas líneas que tocan el círculo, por lo que no tengo que hacer un análisis espacial, solo comparo los intervalos de tiempo para cada especie y puedo estar bastante seguro de que es la misma persona que se encuentra en la comparación .
Ahora estoy buscando una forma en R para identificar aquellas entradas que:
- se hacen el mismo día con un intervalo superpuesto
- y donde es la misma especie
- y que se hicieron desde diferentes puntos de observación (A o B o C o ...))
En este ejemplo, encontré manualmente entradas posiblemente duplicadas de la misma persona. El punto de observación es diferente (A <-> B), la especie es la misma (Sst) y el intervalo de los tiempos de inicio y finalización se superpone.
Ahora crearía un nuevo campo "duplicado" en mi data.frame, dando a ambas filas una identificación común para poder exportarlas y luego decidir qué hacer.
Busqué muchas soluciones disponibles, pero no encontré ninguna sobre el hecho de que tengo que subconjuntar el proceso para la especie (preferiblemente sin bucle) y comparar las filas para 2 + x puntos de observación.
Algunos datos para jugar:
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")
Encontré una solución parcial con la función data.table foverlaps mencionada, por ejemplo, aquí 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)
Por supuesto, esto de alguna manera "funciona", pero en realidad no es lo que me gusta lograr al final.
Primero, tengo que codificar los puntos de observación. Preferiría encontrar una solución con un número arbitrario de puntos.
En segundo lugar, el resultado no está en un formato con el que realmente pueda continuar trabajando fácilmente. Las filas coincidentes se colocan en la misma fila, mientras que mi objetivo es que las filas se coloquen debajo, y en una nueva columna, tendrían un identificador común.
Tercero, tengo que verificar manualmente nuevamente, si un intervalo se superpone desde los tres puntos (que no es el caso con mis datos, pero generalmente podría)
Al final, me gustaría recibir un nuevo data.frame con todos los candidatos identificables por una identificación de grupo que pueda unir de nuevo a las líneas y exportar el resultado como una capa para un examen más detallado.
¿Alguien más ideas de cómo hacer esto?
for
bucles!