2017-03-10 200 views
2

我期望根據開始工作時間和結束工作時間計算不同組的時間差異。我怎麼能告訴R根據他們在一個組中的標籤計算兩行之間的difftime?下面是一個簡單的數據集:如何計算R中變量行之間的時間差?

library(data.table) 


latemail <- function(N, st="2012/01/01", et="2012/02/01") { 
    st <- as.POSIXct(as.Date(st)) 
    et <- as.POSIXct(as.Date(et)) 
    dt <- as.numeric(difftime(et,st,unit="sec")) 
    ev <- sort(runif(N, 0, dt)) 
    rt <- st + ev 

} 

#create our data frame 
set.seed(42) 
dt = latemail(20) 
work = setDT(as.data.frame(dt)) 
work[,worker:= stringi::stri_rand_strings(2, 5)] 
work[,dt:= as.POSIXct(as.character(work$dt), tz = "GMT")] 
work[,status:=NA] 

#order 
setorder(work, worker, dt) 

#add work times 
work$status[1] = "start" 
work$status[5] = "end" 
work$status[6] = "start" 
work$status[10] = "end" 
work$status[11] = "start" 
work$status[15] = "end" 
work$status[16] = "start" 
work$status[20] = "end" 

表現在看起來是這樣的:

    dt worker status 
1: 2012-01-04 23:11:31 VOuRp start 
2: 2012-01-09 15:53:16 VOuRp  NA 
3: 2012-01-15 02:56:45 VOuRp  NA 
4: 2012-01-16 21:12:26 VOuRp  NA 
5: 2012-01-20 16:27:31 VOuRp end 
6: 2012-01-22 15:34:05 VOuRp start 
7: 2012-01-23 15:01:18 VOuRp  NA 
8: 2012-01-29 03:36:56 VOuRp  NA 
9: 2012-01-29 20:11:02 VOuRp  NA 
10: 2012-01-31 02:48:01 VOuRp end 
11: 2012-01-04 10:24:38 u8zw5 start 
12: 2012-01-08 17:02:20 u8zw5  NA 
13: 2012-01-14 23:33:35 u8zw5  NA 
14: 2012-01-15 12:23:52 u8zw5  NA 
15: 2012-01-18 03:53:15 u8zw5 end 
16: 2012-01-21 03:48:08 u8zw5 start 
17: 2012-01-23 02:01:10 u8zw5  NA 
18: 2012-01-26 12:51:10 u8zw5  NA 
19: 2012-01-29 18:23:46 u8zw5  NA 
20: 2012-01-29 22:22:14 u8zw5 end 

答案我在尋找: 最後我想獲得的底值(標工人1和工人2只是因爲不知道如何處理stringi的set.seed())。下面的代碼讓我對工人1中的第一行,但我想每個工人每個班次:

difftime(as.POSIXct("2012-01-20 16:27:31"), as.POSIXct("2012-01-04 23:11:31"), units = "hours") 
    Work time time difference in hours 
    worker 1   377.2667 hours 
    worker 2   . . . . 

在這個例子中,我有一個甚至成立工人之間的值,但假設我有之間的可變行不同的工人會是什麼樣子?我正在假設某種difftime公式?我正在處理大量數據時會使用數據表解決方案。

+0

你怎麼得到這樣的數字? (172.6158和388.6102)。對我而言,你不清楚你想得到什麼。 –

+0

對不起,我失算了。我正在尋找每一個開始的差異,例如:difftime(as.POSIXct(「2012-01-20 16:27:31」),as.POSIXct(「2012-01-04 23:11: 31「),單位=」小時「),工人1的第一班,然後下一班 – LoF10

回答

3

下面是使用data.table一個解決方案:

work[status %in% c("start", "end"), 
     time.diff := ifelse(status == "start", 
     difftime(shift(dt, fill = NA, type = "lead"), dt, units = "hours"), NA), 
     by = worker][status == "start", sum(time.diff), worker] 

我們得到:

worker  V1 
1: VOuRp 580.4989 
2: u8zw5 540.0453 
> 

其中V1有從每個工人啓動結束期間的所有時間的總和。

讓我們一步一步解釋,以便更好地理解。

STEP 1.startend狀態選中所有行:

work.se <- work[status %in% c("start", "end")] 

        dt worker status 
1: 2012-01-04 23:11:31 VOuRp start 
2: 2012-01-20 16:27:31 VOuRp end 
3: 2012-01-22 15:34:05 VOuRp start 
4: 2012-01-31 02:48:01 VOuRp end 
5: 2012-01-04 10:24:38 u8zw5 start 
6: 2012-01-18 03:53:15 u8zw5 end 
7: 2012-01-21 03:48:08 u8zw5 start 
8: 2012-01-29 22:22:14 u8zw5 end 
> 

STEP 2:計算當前行和下一個之間的時間差創建功能。該函數將在data.table對象內調用。我們使用shift功能從同一個包:

getDiff <- function(x) { 
    difftime(shift(x, fill = NA, type = "lead"), x, units = "hours") 
} 

getDiff計算從下一條記錄(集團內)和當前的時間差。它爲最後一行分配NA,因爲沒有下一個值。然後我們排除計算中的NA值。

STEP 3:在data.table語法中調用它:

work.result <- work.se[, time.diff := ifelse(status == "start", 
    getDiff(dt), NA), by = worker] 

我們得到這樣的:

    dt worker status time.diff 
1: 2012-01-04 23:11:31 VOuRp start 377.2667 
2: 2012-01-20 16:27:31 VOuRp end  NA 
3: 2012-01-22 15:34:05 VOuRp start 203.2322 
4: 2012-01-31 02:48:01 VOuRp end  NA 
5: 2012-01-04 10:24:38 u8zw5 start 329.4769 
6: 2012-01-18 03:53:15 u8zw5 end  NA 
7: 2012-01-21 03:48:08 u8zw5 start 210.5683 
8: 2012-01-29 22:22:14 u8zw5 end  NA 

STEP 4:和非NA爲每個time.diff列值worker:

> work.result[status == "start", sum(time.diff), worker] 
    worker  V1 
1: VOuRp 580.4989 
2: u8zw5 540.0453 
> 

data.table對象可經由[]所附連在一起,因此它可以被合併到一個單句的最後部分:

work.se[, time.diff := ifelse(status == "start", 
    getDiff(dt), NA), by = worker][status == "start", sum(time.diff), worker] 

FINAL:把所有在一起成爲一個單獨的句子:

work[status %in% c("start", "end"), 
    time.diff := ifelse(status == "start", 
    difftime(shift(dt, fill = NA, type = "lead"), dt, units = "hours"), NA), 
    by = worker][status == "start", sum(time.diff), worker] 

檢查此linkdata.table基本語法。 我希望這會有所幫助,請讓我們知道,如果它是你想要的

+0

謝謝大衛!這對數據集的第一個版本有意義。我想知道如何我可能會接近我的編輯版本?每個司機有兩組或多組起止點? – LoF10

+0

@ LoF10,然後我會更新答案 –

+1

這非常有幫助,正是我所需要的。謝謝大衛! – LoF10