2015-06-04 9 views
8

Ich habe das folgende Problem: Geben Sie eine Reihe von nicht überlappenden Intervallen in einer data.table, melden Sie die Lücken zwischen den Intervallen.Finden von Lücken zwischen Intervallen mit data.table

Ich habe dies einmal in SQL implementiert, aber ich habe Probleme mit data.table wegen des Fehlens einer Führungsfunktion oder einer Verzögerungsfunktion. Der Vollständigkeit halber habe ich here den SQL-Code. Ich weiß, dass die Funktionalität in data.table Version 1.9.5 implementiert wurde. wie durch die changelog. Ist das mit data.table möglich, ohne viele Merges und ohne Lag oder Lead-Funktion zu machen?

Im Prinzip bin ich nicht gegen die Verwendung von Zusammenführungen (aka Joins), solange die Leistung nicht leidet. Ich denke, das hat eine einfache Implementierung, aber ich kann mir nicht vorstellen, wie ich die vorherige Endzeit als Startzeit meiner Lückestabelle bekommen kann.

Zum Beispiel:

# The numbers represent seconds from 1970-01-01 01:00:01 
dat <- structure(
    list(ID = c(1L, 1L, 1L, 2L, 2L, 2L), 
     stime = structure(c(as.POSIXct("2014-01-15 08:00:00"), 
          as.POSIXct("2014-01-15 11:00:00"), 
          as.POSIXct("2014-01-16 11:30:00"), 
          as.POSIXct("2014-01-15 09:30:00"), 
          as.POSIXct("2014-01-15 12:30:00"), 
          as.POSIXct("2014-01-15 13:30:00") 
          ), 
         class = c("POSIXct", "POSIXt"), tzone = ""), 
     etime = structure(c(as.POSIXct("2014-01-15 10:30:00"), 
          as.POSIXct("2014-01-15 12:00:00"), 
          as.POSIXct("2014-01-16 13:00:00"), 
          as.POSIXct("2014-01-15 11:00:00"), 
          as.POSIXct("2014-01-15 12:45:00"), 
          as.POSIXct("2014-01-15 14:30:00") 
          ), 
         class = c("POSIXct", "POSIXt"), tzone = "") 
), 
    .Names = c("ID", "stime", "etime"), 
    sorted = c("ID", "stime", "etime"), 
    class = c("data.table", "data.frame"), 
    row.names = c(NA,-6L) 
) 

dat <- data.table(dat) 

Daraus ergibt sich:

ID    stime    etime 
1 2014-01-15 10:30:00 2014-01-15 11:00:00 
1 2014-01-15 12:00:00 2014-01-16 11:30:00 
2 2014-01-15 11:00:00 2014-01-15 12:30:00 
2 2014-01-15 12:45:00 2014-01-15 13:30:00 

Hinweis: die Lücken gleichmäßig über Tage gemeldet werden.

+2

Vermissen Sie nicht eine Zeile hier oder mir fehlt etwas? –

+3

Randnotiz: 'dat <- data.table (dat)' ist eine Verschwendung von Speicher. Verwenden Sie stattdessen 'setDT (dat)'. – Arun

+2

Ich denke, dass dies mit kleinen Änderungen an @ eddi's Antwort in Ihrem vorherigen Q getan werden kann. – Arun

Antwort

5

Eine Variation auf Davids Antwort, wahrscheinlich etwas weniger effizient, aber einfacher tippen:

setkey(dat, stime)[, .(stime=etime[-.N], etime=stime[-1]), by=ID] 

Produziert:

ID    stime    etime 
1: 1 2014-01-15 10:30:00 2014-01-15 11:00:00 
2: 1 2014-01-15 12:00:00 2014-01-16 11:30:00 
3: 2 2014-01-15 11:00:00 2014-01-15 12:30:00 
4: 2 2014-01-15 12:45:00 2014-01-15 13:30:00 

setkey nur sicher Tabelle sortiert zu machen ist, zum Zeitpunkt.

5

Wenn ich etwas nicht vermisse, fehlt eine Zeile in Ihrer gewünschten Ausgabe, also hier ist mein Versuch, shift von der Devel-Version wie Sie erwähnt.

library(data.table) ## v >= 1.9.5 
indx <- dat[, .I[-.N], by = ID]$V1 
dat[, .(ID, stimes = etime, etime = shift(stime, type = "lead"))][indx] 
res 
# ID    stime    etime 
# 1: 1 2014-01-15 10:30:00 2014-01-15 11:00:00 
# 2: 1 2014-01-15 12:00:00 2014-01-16 11:30:00 
# 3: 2 2014-01-15 11:00:00 2014-01-15 12:30:00 
# 4: 2 2014-01-15 12:45:00 2014-01-15 13:30:00 
Verwandte Themen