2014-09-12 2 views
8

У меня есть список людей и их рабочее начало и время окончания в течение дня. Я хочу построить кривую, показывающую общее количество людей, работающих в любую минуту в день. Я мог бы добавить только 1440 дополнительных условных логических переменных для каждой минуты дня и суммировать их, но это кажется очень неэлегантным. Мне интересно, есть ли лучший способ сделать это (интегралы?).R - временные интервалы перекрытия участка

Вот код для генерации ФРА с моими данными выборки:

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 
} 

создать выборочные данные, вы можете сделать что-то вроде:

DF <- sample_wt() 
+0

Это не образец данных, это функция. – 2014-09-12 07:02:35

+1

@Pascal да, функция, которая может использоваться для создания обширных данных. – agstudy

+0

@agstudy OP не предоставляет способ его использования. – 2014-09-12 07:06:25

ответ

5

Здесь один варианта использования IRanges пакета из Bioconductor ,

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

Я думаю, что в третьей строке кода есть ошибка: 'rangeA < - IRanges (as.numeric (DF $ start), as.numeric (DF $ end)) '(DF вместо диапазоновA) –

+0

@arumbay да спасибо. Я исправил опечатку. – agstudy

+0

Я не могу найти функцию 'sample_wt'. Из какого пакета это? –

0

Конечно, это может быть улучшен, но это, кажется, сделать это:

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

Я не lubridate установлен, так что я произвел data.frame через Sys.time вместо now (предположим, они должны быть похожими). Это может сделать трюк:

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

Ницца! Мне нравится больше, чем мне нравится, и «microbenchmark» говорит, что они одинаково быстры. Просто обрезайте лишние '0' на каждом конце вектора, и это идеально. –

Смежные вопросы