2017-05-05 35 views
1

我有兩個數據框:「探針」和「事件」。以下代碼將生成這些數據幀的可重現樣本。 Probes.subset是來自探測器的所有觀測數據的一個數據幀,它與Events中的日期時間範圍相交。 下面的代碼會生成6個事件...實際上我有近200個謹慎的事件。多個日期範圍的條件連接

目標:我需要根據時間戳將事件中的Event.name連接到Probes.subset中的每個對應觀察值,以便每個觀察值都與正確的事件關聯。

have previously tried a FOR loop但是這是令人難以置信的緩慢,沒有完成我的數據是超過18萬行長。我有一種感覺,這可以通過編寫一個函數和使用像apply這樣的東西來解決,但我是R中的一個完整的新手,並且沒有創建工作。

library(dplyr) 

# Generate Probes data 
start <- as.POSIXct("01/06/2016 01:00", format = "%d/%m/%Y %H:%M") 
end <- start + as.difftime(1, units = "days") 

Timestamp <- seq(from = start, to = end, by = "10 mins") 
Value <- round(runif(145) * 100, 2) 

Probes <- data.frame(Timestamp, Value) 

# Generate Events data 
Event.name <- seq(1, 6) 

Event.start <- as.POSIXct(c("01/06/2016 01:20", "01/06/2016 05:00", 
          "01/06/2016 06:30", "01/06/2016 12:00", 
          "01/06/2016 17:40", "01/06/2016 19:20"), 
          format = "%d/%m/%Y %H:%M") 

Event.end <- as.POSIXct(c("01/06/2016 02:00", "01/06/2016 05:30", 
          "01/06/2016 07:20", "01/06/2016 14:00", 
          "01/06/2016 18:10", "01/06/2016 21:40"), 
          format = "%d/%m/%Y %H:%M") 

Events <- data.frame(Event.name, Event.start, Event.end) 

# Subset probes data to fall within Events bounds 
Probes.subset <- Probes %>% 
    mutate(InRange = Timestamp %in% unlist(Map(
    `:`, 
    Events$Event.start, 
    Events$Event.end 
))) %>% 
    filter(InRange == "TRUE") 
+0

[A類似的問題](http://stackoverflow.com/questions/23095896/merging-two-dataframes-on- a-date-range-in-r)處理連接日期範圍,但它們的示例在數據框之間有一個共同的列。我不能評論他們的問題,因爲我的代表太低。 – Ciaran

+0

這會產生你想要的結果嗎? 'unlist(lapply(Probes.subset $ Timestamp,function(x)which(x> = Events $ Event.start&x <= Events $ Event.end)))'。我試圖運行,但出現以下錯誤 - 您可以指定這在'Probes.subset' – Gopala

+0

@Gopala列:在$'' 錯誤< - data.frame'('* TMP *',「事件」 ,值= C(1L,1L,1L,1L,: 更換具有43行,數據已經54' – Ciaran

回答

4

在SQL你可以使用as同時加入到指定別名爲不同的數據集。這使您可以從每個數據集中選擇一個特定的列。採用這個答案的代碼,你可以這樣做:

library(sqldf) 
res <- sqldf("SELECT l.*, r.`Event.name` 
     FROM Probes as l 
     LEFT JOIN Events as r 
     ON l.Timestamp BETWEEN r.`Event.start` AND r.`Event.end`") 

head(res) 
#   Timestamp Value Event.name 
#1 2016-06-01 01:00:00 60.73   NA 
#2 2016-06-01 01:10:00 14.01   NA 
#3 2016-06-01 01:20:00 17.14   1 
#4 2016-06-01 01:30:00 43.64   1 
#5 2016-06-01 01:40:00 27.05   1 
#6 2016-06-01 01:50:00 57.10   1 

一個說明 - 我會小心你的數據建立以來的Events 5排你有開始時間>結束時間。


而且快速data.table的解決辦法是使用foverlaps

library(data.table) 
setDT(Probes)[,Time2 := Timestamp] #Clean data 
setDT(Events)[, `:=`(start = min(Event.start, Event.end), end = max(Event.start, Event.end)), by = (seq_len(nrow(Events)))] 

setkey(setDT(Events), start, end) 
res2 <- foverlaps(setDT(Probes), Events, by.x = c("Timestamp", "Time2"), nomatch = NA)[, c("Time2", "Event.start", "Event.end", "start","end") := NULL] 
+0

我發現了之後我張貼,給它現在一試! – Ciaran

+0

,完美的工作!非常感謝你的幫助,這一直是現在相當長的一段headwreck。 我打算讓我的頭周圍現在使用的R內的SQL ...還是一個新手!+1 – Ciaran

+1

沒問題!我發現SQL對於這些類型的連接非常有用。關於我編輯的速度,以包含一個快速的'data.table'方法。雖然語法不是非常友好 –