2014-09-12 22 views
8

Ich habe eine Liste von Menschen und ihre Arbeitsbeginn und -ende Zeiten während eines Tages. Ich möchte eine Kurve zeichnen, die die Gesamtzahl der Menschen zeigt, die jede Minute am Tag arbeiten. Ich könnte nur 1440 zusätzliche bedingte boolesche Variablen für jede Minute des Tages hinzufügen und zusammenfassen, aber das scheint sehr unelegant zu sein. Ich frage mich, ob es einen besseren Weg gibt, es zu tun (Integrale?).R - Plot überlappende Zeitintervalle

Hier ist der Code eine df mit meiner Beispieldaten zu erzeugen:

sample_wt <- function() { 

    require(lubridate) 

    set.seed(10) 

    worktime <- data.frame(
      ID = c(1:100), 
      start = now()+abs(rnorm(100,4800,2400)) 
      ) 

    worktime$end <- worktime$start + abs(rnorm(100,20000,10000)) 

    worktime$length <- difftime(worktime$end, worktime$start, units="mins") 

    worktime 
} 

ein Beispieldaten zu erstellen, können Sie so etwas tun:

DF <- sample_wt() 
+0

Es ist keine Beispieldaten, es ist eine Funktion. –

+1

@Pascal ja, eine Funktion, die verwendet werden kann, um umfangreiche Daten zu erstellen. – agstudy

+0

@agstudy Das OP bietet keine Möglichkeit, es zu benutzen. –

Antwort

5

Hier eine Option IRanges Paket von Bioconductor mit .

library(IRanges) 
## generate sample 
DF <- sample_wt() 
## create the range from the sample data 
rangesA <- IRanges(as.numeric(DF$start), as.numeric(DF$end)) 
## create one minute range 
xx = seq(min(DF$start),max(DF$end),60) 
rangesB <- IRanges(as.numeric(xx),as.numeric(xx+60)) 
## count the overlaps 
ov <- countOverlaps(rangesB, rangesA, type="within") 
## plot the result 
plot(xx,ov,type='l') 

enter image description here

+0

Ich denke, es ist ein Fehler in der dritten Codezeile, sollte sein: 'RangesA < - IRanges (as.numeric (DF $ start), as.numerisch (DF $ end)) '(DF statt rangesA) –

+0

@arumbay ja danke. Ich habe den Tippfehler korrigiert. – agstudy

+0

Ich kann die 'sample_wt'-Funktion nicht finden. Aus welchem ​​Paket ist das? –

0

Sicher kann es verbessert werden, aber dies scheint, es zu tun:

time_range <- seq(min(DF$start), max(DF$end), 60) 
result <- integer(length(time_range)) 
for (t in seq_along(time_range)) { 
    result[t] <- sum(DF$start <= time_range[t] & DF$end >= time_range[t]) 
} 
1

Ich habe nicht lubridate installiert, so produzierte ich die data.frame durch Sys.time statt von now (denke, sie sollten ähnlich sein). Dies könnte den Trick machen:

minutes<-seq(as.POSIXct(paste(sep="",Sys.Date()," 00:00:00")),by="min",length.out=24*60) 
    rowSums(outer(minutes,worktime$start,">") & outer(minutes,worktime$end,"<")) 
+0

Nice one! Ich mag es mehr als ich mag, und 'microbenchmark' sagt, sie sind genauso schnell. Schneiden Sie einfach die zusätzlichen '0' an jedem Ende des Vektors und es ist perfekt. –