2017-06-21 70 views
1

我有兩個數據幀,一個包含測量值和時間戳,具有開始和結束時間的其它含測量週期:匹配數據

txt1 <- "  v1  datetime 
23 '2016-02-14 12:00:10' 
12 '2016-02-14 12:03:10' 
21 '2016-02-14 12:50:00' 
52 '2016-02-14 13:01:10' 
53 '2016-02-14 13:05:50' 
23 '2016-02-14 13:09:25' 
95 '2016-02-14 13:20:10' 
11 '2016-02-14 13:21:00' 
64 '2016-02-14 13:25:12' 
41 '2016-02-14 13:45:34' 
14 '2016-02-14 13:53:08' 
" 

txt2 <- " mp  start  end 
1 '2016-02-14 12:00:00' '2016-02-14 12:11:00' 
2 '2016-02-14 12:58:00' '2016-02-14 13:13:00' 
3 '2016-02-14 13:22:00' '2016-02-14 14:00:00' 
" 
d1 <- read.table(textConnection(txt1), header = TRUE, 
       colClasses = c("integer", "POSIXct")) 

d2 <- read.table(textConnection(txt2), header = TRUE, 
       colClasses = c("integer", "POSIXct" ,"POSIXct")) 

我想要分配的正確的測量期間每次測量(保留不匹配的行):

"  v1  datetime  mp 
23 '2016-02-14 12:00:10' 1 
12 '2016-02-14 12:03:10' 1 
21 '2016-02-14 12:50:00' NA 
52 '2016-02-14 13:01:10' 2 
53 '2016-02-14 13:05:50' 2 
23 '2016-02-14 13:09:25' 2 
95 '2016-02-14 13:20:10' NA 
11 '2016-02-14 13:21:00' NA 
64 '2016-02-14 13:25:12' 3 
41 '2016-02-14 13:45:34' 3 
14 '2016-02-14 13:53:08' 3 
" 

我目前的做法是使用嵌套的for循環,但我正在尋找一個更有效的方法。

+1

嘗試[foverlaps](https://www.rdocumentation.org/packages/data.table/versions/1.10.4/topics/foverlaps)? –

+0

[範圍和單日期之間的日期合併](https://stackoverflow.com/questions/38379206/date-merging-between-range-and-single-dates/38380091#38380091) –

回答

1

使用sapply的基本R方法。對於datetime列中的每個值d1我們檢查它是否落入d2中的任何一行的範圍內。如果它落在any行的範圍內,則它返回相應的mp值或返回NA

d1$tmp <- sapply(d1$datetime, function(x) { 
      mtch = x >= d2$start & x <= d2$end 
      ifelse(any(mtch), d2$mp[mtch], NA) 
      }) 
d1 

# v1   datetime tmp 
#1 23 2016-02-14 12:00:10 1 
#2 12 2016-02-14 12:03:10 1 
#3 21 2016-02-14 12:50:00 NA 
#4 52 2016-02-14 13:01:10 2 
#5 53 2016-02-14 13:05:50 2 
#6 23 2016-02-14 13:09:25 2 
#7 95 2016-02-14 13:20:10 NA 
#8 11 2016-02-14 13:21:00 NA 
#9 64 2016-02-14 13:25:12 3 
#10 41 2016-02-14 13:45:34 3 
#11 14 2016-02-14 13:53:08 3 
+0

謝謝,我試圖包裝我的頭腦圍繞着解決方案的原始版本(編輯之前)如何工作,如何指定'd2 $ mp'列 – ringgord

+1

@ringgord原始版本的工作原理是因爲您的'mp'列中的值爲1,2,3 ,用任何其他值替換它,它會給你錯誤的值。以前的版本使用'which'給出了匹配的索引位置,而你需要的是與該索引匹配的'mp'列中的值。 –

1

不知道這是最有效的方式,但我會做到這一點的辦法是先轉換d2到一個列表(其中每行是一個列表項),然後lapply在列表中指定正確的mpd1:應用函數內

d1$mp <- NA 
d2_list <- split(d2, seq(nrow(d2))) 

lapply(
    d2_list, 
    function(row) d1$mp[d1$datetime >= row$start & d1$datetime <= row$end] <<- row$mp 
) 

注意<<-賦值運算符。您還可以在控制檯中獲得一些不相關的打印輸出,但ds1將按預期進行修改。