2017-08-26 51 views
2

我有一個數據幀(「觀察」),其格式爲H:M(「時間」)。在第二個數據幀(「間隔」)中,我的時間範圍由「From」和「Till」變量定義,格式也爲H:M以不同時間間隔計算時間戳 - 以跨越午夜的間隔問題

我想統計每個區間內的觀測值的數量。我一直在使用data.table中的between,這在包含日期時一直沒有任何問題。

但是,現在我只有時間戳,沒有日期。這導致在跨越午夜(20:00 - 05:59)的時間間隔中發生的一些問題。這些時間不計入我嘗試過的代碼中。

實例下

interval.data <- data.frame(From = c("14:00", "20:00", "06:00"), Till = c("19:59", "05:59", "13:59"), stringsAsFactors = F) 
observations <- data.frame(Time = c("14:32", "15:59", "16:32", "21:34", "03:32", "02:00", "00:00", "05:57", "19:32", "01:32", "02:22", "06:00", "07:50"), stringsAsFactors = F) 

interval.data 
#  From  Till 
# 1: 14:00:00 19:59:00 
# 2: 20:00:00 05:59:00 # <- interval including midnight 
# 3: 06:00:00 13:59:00 

observations 
#  Time 
# 1: 14:32:00 
# 2: 15:59:00 
# 3: 16:32:00 
# 4: 21:34:00 # Row 4-8 & 10-11 falls in 'midnight interval', but are not counted 
# 5: 03:32:00 # 
# 6: 02:00:00 # 
# 7: 00:00:00 # 
# 8: 05:57:00 # 
# 9: 19:32:00 
# 10: 01:32:00 # 
# 11: 02:22:00 # 
# 12: 06:00:00 
# 13: 07:50:00 

library(data.table) 
library(plyr) 
adply(interval.data, 1, function(x, y) sum(y[, 1] %between% c(x[1], x[2])), y = observations) 

# From Till V1 
# 1 14:00 19:59 4 
# 2 20:00 05:59 0 # <- zero counts - wrong! 
# 3 06:00 13:59 2 
+0

的一個結束時那些永遠是你的時間間隔,或者這只是一個大一個小例子數據集? – SymbolixAU

+0

更大集合的相同結構 – MLEN

+0

使用'adply'與1的邊距類型會使data.table的使用無關緊要。 –

回答

1

我只是調整了你的代碼,以獲得期望的結果。希望這可以幫助!

adply(interval.data, 1, function(x, y) 
    if(x[1] > x[2]) return(sum(y[, 1] %between% c(x[1], 23:59), y[, 1] %between% c(00:00, x[2]))) else return(sum(y[, 1] %between% c(x[1], x[2]))), y = observations) 

輸出是:

From Till V1 
1 14:00 19:59 4 
2 20:00 05:59 7 
3 06:00 13:59 2 
+0

這是完美的。只需引用「23:59」和「00:00」。雖然它的確適用於上面的例子。 – MLEN

4

一種方法是在data.table使用非球菌加盟,並與時間字符串工作的輔助函數as.ITime

您會遇到跨越午夜的間隔問題,但是,應該只有其中之一。並且,如果您對每個「組」間隔的觀察次數感興趣,則可以將該組視爲等同於其他組的「不」。

例如,首先將您data.framedata.table

library(data.table) 

## set your data.frames as `data.table` 
setDT(interval.data) 
setDT(observations) 

然後使用as.ITime轉換爲時間整數表示

## convert time stamps 
interval.data[, `:=`(FromMins = as.ITime(From), 
        TillMins = as.ITime(Till))] 

observations[, TimeMins := as.ITime(Time)] 
## you could combine this step with the non-equi join directly, but I'm separating it for clarity 

您現在可以使用非等距聯接找到每次落入的時間間隔。他指出,那些reutrn時報「NA」實際上是那些屬於午夜跨度區間內

interval.data[ 
    observations 
    , on = .(FromMins <= TimeMins, TillMins > TimeMins) 
    ] 

#  From Till FromMins TillMins Time 
# 1: 14:00 19:59  872  872 14:32 
# 2: 14:00 19:59  959  959 15.59 
# 3: 14:00 19:59  992  992 16:32 
# 4:  NA NA  1294  1294 21:34 
# 5:  NA NA  212  212 03:32 
# 6:  NA NA  120  120 02:00 
# 7:  NA NA  0  0 00:00 
# 8:  NA NA  357  357 05:57 
# 9: 14:00 19:59  1172  1172 19:32 
# 10: NA NA  92  92 01:32 
# 11: NA NA  142  142 02:22 
# 12: 06:00 13:59  360  360 06:00 
# 13: 06:00 13:59  470  470 07:50 

然後拿到observatins的數量區間的羣體,你剛纔.N每個時間點,歸納其可以只被鏈接到上述聲明

interval.data[ 
    observations 
    , on = .(FromMins <= TimeMins, TillMins > TimeMins) 
][ 
    , .N 
    , by = .(From, Till) 
] 

#  From Till N 
# 1: 14:00 19:59 4 
# 2: NA NA 7 
# 3: 06:00 13:59 2 

NA組對應於跨越午夜

+0

你可以在這裏使用'as.ITime',而不是轉換爲分鐘嗎? – Henrik

+0

@亨利克 - 當然是啊!我總是在'data.table'中得到'ITime' ...我會更新 – SymbolixAU