R? De iki kriter daha üst üste binen zaman aralıklarının belirlenmesi


10

Çift / örtüşen girişler için daha uzun bir süre yapılan kuş gözlemlerini kontrol etmeliyim.

Farklı noktalardan (A, B, C) gözlemciler gözlemler yaptılar ve bunları kağıt haritalarda işaretlediler. Bir çizgiye getirilen çizgiler, türler, gözlem noktası ve gördükleri zaman aralıkları için ek veriler içerir.

Normalde, gözlemciler gözlem yaparken birbirleriyle telefon aracılığıyla iletişim kurarlar, ancak bazen unuturlar, bu yüzden o yinelenen hatları alıyorum.

Verileri zaten daireye dokunan çizgilere indirgedim, bu yüzden uzamsal bir analiz yapmak zorunda değilim, ancak sadece her tür için zaman aralıklarını karşılaştırıyorum ve karşılaştırmanın bulduğu ile aynı kişi olduğundan emin olabilirim .

Şimdi R bu girişleri tanımlamak için bir yol arıyorum:

  • aynı gün üst üste binen aralıklarla yapılır
  • ve aynı türün nerede olduğu
  • ve farklı gözlem noktalarından (A veya B veya C veya ...) yapılmış)

resim açıklamasını buraya girin

Bu örnekte, aynı kişinin muhtemelen yinelenen girişlerini buldum. Gözlem noktası farklıdır (A <-> B), türler aynıdır (Sst) ve başlangıç ​​ve bitiş zamanları aralığı çakışır.

resim açıklamasını buraya girin

Şimdi benim veri.frame yeni bir alan "yinelenen" oluşturmak, her iki satır onları vermek ve daha sonra ne yapmak karar vermek için ortak bir kimlik vererek.

Zaten mevcut çözümler için çok şey araştırdım, ancak türler için işlemi (tercihen bir döngü olmadan) alt kümeye ayarlamak ve 2 + x gözlem noktaları için satırları karşılaştırmak zorunda olduğumla ilgili bir şey bulamadım.

Oynamak için bazı veriler:

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")

Burada belirtilen data.table işlevi foverlaps ile kısmi bir çözüm buldum 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)

Tabii ki, bu bir şekilde "işe yarıyor", ama sonunda başarmayı sevdiğim şey bu değil.

İlk olarak, gözlem noktalarını zor kodlamalıyım. Rastgele sayıda puan alan bir çözüm bulmayı tercih ederim.

İkincisi, sonuç, kolayca çalışmaya devam edebileceğim bir formatta değil. Eşleşen satırlar aslında aynı satıra yerleştirilirken, hedefim satırların altına konulmasını sağlamak ve yeni bir sütunda ortak bir tanımlayıcıya sahip olmaktır.

Üçüncüsü, üç noktadan da bir aralık çakışıyorsa, tekrar manuel olarak kontrol etmeliyim (verilerimde durum böyle değil, ancak genellikle olabilir)

Sonunda, yeni bir data.frame almak istiyorum, tüm adaylarla grup kimliğiyle tanımlanabilir.

Peki bunun nasıl yapılacağına dair daha fazla fikir olan var mı?


Tam olarak anladığımdan emin değilim, ancak PostgreSQL'de oldukça basit bir görev gibi görünüyor. Zaman aralıkları için işlevler vardır. Anladığım kadarıyla PostgreSQL ve R arasında veri paylaşmak kolay olmalı
Nicklas Avén

İtiraf etmeliyim ki Postgres'in sıfır bilgisine sahip değilim, ama aslında, bu akşam bir bira içerken, bunun için bazı sql şeylerinin mevcut olabileceği fikri vardı. Diğer işlemlerim için veri kümesi ile ilgiliyim, R THE aracı olsa da, sql fonksiyonlarının bazı paketler aracılığıyla R içinde de yapılabileceğini biliyorum. Araştırılıyor ....
Bernd V.

Veri seti ne kadar büyük - yüzlerce, binlerce, milyonlarca satır? SQL işlevleri için sqldf buldunuz mu?
Simbamangu

Bu arada çalışan bir çözüm buldum. Yazıklar olsun bana şimdiye kadar göndermedim. Başkaları için daha genel hale getirmek zorunda kalacak, ve sonra asap göndereceğim.
Bernd

Tamamen vektörleştirilmişse ve fordöngüler kullanmıyorsa + 1'leyecektir!
Simbamangu

Yanıtlar:


1

Bazı yorumcular belirttiği gibi, SQL oldukça karmaşık kısıtlama kümelerini ifade etmek için iyi bir seçenektir. Sqldf paketi kolay bir ilişkisel veritabanını kendiniz kurmaya gerek kalmadan Ar SQL'ın gücünü kullanmak mümkün kılar.

İşte SQL kullanarak bir çözüm. Koşma önce, sizin verinin aralık sütunları yeniden adlandırmak zorunda startTimeve endTimeadı nedeniyle fromSQL ayrılmıştır.

library(reshape2)
library(sqldf)

dupes_wide <- sqldf("SELECT hex(randomblob(16)) dupe_id, x.bird_id x_bird_id, y.bird_id y_bird_id
                     FROM testdata x JOIN testdata y
                          ON (x.startTime <= y.endTime)
                         AND (x.endTime >= y.startTime)
                         AND (x.species = y.species)
                         AND (x.obsPoint < y.obsPoint)")
dupes_long <- melt(dupes_wide, id.vars='dupe_id', value.name='bird_id')
merge(testdata, dupes_long[, c('dupe_id', 'bird_id')], by='bird_id', all.x=TRUE)

Anlamaya yardımcı olmak için SQL yanıtı şöyle dupes_widegörünür:

                         dupe_id x_bird_id y_bird_id
253FCC7A58FD8401960FC5D95153356C 20150727_1130_1430_A_2 20150727_1120_1430_B_1
9C1C1A13306ECC2DF78004D421F70CE6 20150727_1130_1430_A_5 20150727_1120_1430_B_4
1E8316DBF631BBF6D2CCBD15A85E6EF3 20150812_0907_1208_A_5 20150812_0900_1225_B_6

Kendi kendine katılma FROM testdata x JOIN testdata y : Tek bir veri kümesinden satır çiftleri bulmak kendi kendine katılmadır. Her satırı birbirimizle karşılaştırmamız gerekiyor. ONSentezleme çiftleri tutmak için kısıtlamalar listeler.

Çakışan aralık : Bu SQL'de ( kaynak ) kullandığım örtüşme tanımının foverlapssizin için yaptıklarından farklı olduğundan eminim. Daha önce de gözlem gerektirir "içinde" türü, kullanılan obsPointdaha sonra en gözlem içinde tamamen olmak obsPoint(ama eğer, örneğin, karşıtını özlüyor C 'nin gözlem içinde tamamen B s'). Neyse ki, farklı bir çakışma tanımını kodlamanız gerekiyorsa SQL'de kolaydır.

Farklı noktalar : Farklı gözlem noktalarından kopyaların yapılmasıyla ilgili kısıtlamanız gerçekten ifade edilecektir (x.obsPoint <> y.obsPoint). Bunu yazmış olsaydım, SQL yinelenen her çifti iki kez döndürürdü, sadece kuşlar her satırdaki sırayı değiştirdi. Bunun yerine <a'yı yalnızca satırların benzersiz yarısını tutmak için kullandım . (Bunu yapmanın tek yolu bu değil)

Benzersiz yinelenen kimlik : Önceki çözümünüzde olduğu gibi SQL'in kendisi de aynı satırdaki kopyaları listeler. hex(randomblob(16))SQLite'de her bir çift için benzersiz kimlikler oluşturmak için hacky ( henüz önerilen ) bir yoldur.

Çıktı biçimi : Aynı satırdaki kopyaları beğenmediniz, bu nedenle meltbunları böler ve mergeyinelenen kimlikleri ilk veri çerçevenize geri atar.

Sınırlamalar : Çözümüm , aynı kuşun ikiden fazla parçada yakalandığı durumu ele almıyor . Daha hileli ve biraz kötü tanımlanmış. Örneğin, zaman aralıkları

    | - Kuş1 - |
             | - Bird2 - |
                      | - Bird3 - |

Sonra Bird1 kopyası Bird2 kopyası, Bird3 ama vardır Bird1 ve Bird3 çiftleri?

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.