2016-05-12 81 views
1

假設我有兩個dataframes之間的最短時間差,找到兩個dataframes

df1 

id  time1 
1   2016-04-07 21:39:10 
1   2016-04-05 11:19:17 
2   2016-04-03 10:58:25 
2   2016-04-02 21:39:10 

df2 

id  time2 
1   2016-04-07 21:39:11 
1   2016-04-05 11:19:18 
1   2016-04-06 21:39:11 
1   2016-04-04 11:19:18 
2   2016-04-03 10:58:26 
2   2016-04-02 21:39:11 
2   2016-04-04 10:58:26 
2   2016-04-05 21:39:11 

我想找到在DF1每個條目,在DF2最短的時間差。假設我們取第一個入口,它有id 1,所以我想通過df2循環,過濾id 1,然後檢查df1的一個入口和df2的剩餘入口之間的時間差,找到最短的差值並獲取相應的入口。我的樣本輸出應該

id  time     time2     diff(in secs) 
1   2016-04-07 21:39:10 2016-04-07 21:39:10  1 
1   2016-04-05 11:19:17 2016-04-05 11:19:17  1 
2   2016-04-03 10:58:25 2016-04-03 10:58:25  1 
2   2016-04-02 21:39:10 2016-04-02 21:39:10  1 

,以下是我的嘗試,

for(i in unique(df1$id)){ 
    temp1 = df1[df1$id == i,] 
    temp2 = df2[df2$id == i,] 
    for(j in unique(df1$time1){ 
    for(k in unique(df2$time2){ 
     diff = abs(df1$time1[j] - df2$time2[k] 
     print(diff)}}} 

我不能在此之後的進步,越來越多的錯誤。有誰能幫我糾正這個問題嗎?可能會建議一個更有效的方法來做到這一點?任何幫助,將不勝感激。

更新:

重放數據:

df1 <- data.frame(
     id = c(1,1,2,2), 
     time1 = c('2016-04-07 21:39:10', '2016-04-05 11:19:17', '2016-04-03 10:58:25', '2016-04-02 21:39:10') 
    ) 

    df2 <- data.frame(
     id = c(1,1,1,1,2,2,2,2), 
     time2 = c('2016-04-07 21:39:11', '2016-04-05 11:19:18','2016-04-07 21:39:11', '2016-04-05 11:19:18', '2016-04-03 10:58:26', '2016-04-02 21:39:11','2016-04-03 10:58:26', '2016-04-02 21:39:11') 
    ) 

df1$time1 = as.POSIXct(df1$time1) 
df2$time2 = as.POSIXct(df2$time2) 
+0

能否請你添加代碼,生成'df1'和'df2' – Divi

+0

做'id's在所有問題? ?聽起來像'id'內的最短差異 – jaimedash

+0

@jaimedash是與相應的時間一起 – haimen

回答

2

您使用dplyr可以實現這一點。基本上這個想法是因爲我們想要創建一個條目,我們將在df1中爲每個元素分配一個新的ID(在這種情況下,我只稱它爲rowname)。

之後,我們感興趣的是加入id上的兩個數據框,並根據最小絕對差值對它們進行過濾。

library(dplyr) 

df1$time1 <- as.POSIXct(as.character(df1$time1)) 
df2$time2 <- as.POSIXct(as.character(df2$time2)) 

df1 %>% 
    add_rownames("rowname") %>% 
    left_join(df2, "id") %>% 
    mutate(diff=time2-time1) %>% 
    group_by(rowname) %>% 
    filter(min(abs(diff)) == abs(diff)) %>% 
    distinct 

這是我的輸出:

Source: local data frame [4 x 5] 
Groups: rowname [4] 

    rowname id    time1    time2 diff 
    (chr) (dbl)    (time)    (time) (dfft) 
1  1  1 2016-04-07 21:39:10 2016-04-07 21:39:11 1 secs 
2  2  1 2016-04-05 11:19:17 2016-04-05 11:19:18 1 secs 
3  3  2 2016-04-03 10:58:25 2016-04-03 10:58:26 1 secs 
4  4  2 2016-04-02 21:39:10 2016-04-02 21:39:11 1 secs  
+0

非常感謝!有效 – haimen

1

你也可以做到這一點的基礎R.生成隨機日期(有用的),我借和編輯從elsewhere on StackOverflow一個不錯的功能:

latemail <- function(N, st="2011/01/01", et="2016/12/31") { 
    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)) 
    return(st + ev) 
} 
df1 <- data.frame(id=c(1,1,2,2), time1=latemail(4)) 
df2 <- data.frame(id=c(rep(1,4), rep(2,4)), time2=latemail(8)) 

然後你的答案可以在兩行中實現:

shortest <- sapply(df1$time1, function(x) which(abs(df2$time2 - x) == min(abs(df2$time2 - x)))) 
cbind(df1, df2[shortest,]) 

輸出:

id    time1 id    time2 
1 2011-10-08 02:00:21 1 2011-08-17 18:07:47 
1 2012-05-06 17:49:03 1 2012-09-04 19:52:40 
2 2013-10-29 13:14:51 1 2012-10-29 20:09:31 
2 2016-06-17 19:23:43 2 2015-11-24 02:07:15 
0

如果您有data.table工作:

library(data.table) 
df1 <- data.table(
    id = c(1,1,2,2), 
    time1 = c('2016-04-07 21:39:10', '2016-04-05 11:19:17', '2016-04-03 10:58:25', '2016-04-02 21:39:10') 
) 

df2 <- data.table(
    id = c(1,1,1,1,2,2,2,2), 
    time2 = c('2016-04-07 21:39:11', '2016-04-05 11:19:18','2016-04-07 21:39:11', '2016-04-05 11:19:18', '2016-04-03 10:58:26', '2016-04-02 21:39:11','2016-04-03 10:58:26', '2016-04-02 21:39:11') 
) 

df1$time1 = as.POSIXct(df1$time1) 
df2$time2 = as.POSIXct(df2$time2) 

res <- df1[df2, .(time1, time2), by = .EACHI, on = "id"][, diff:= abs(time2 -time1)] 
setkey(res, id, time1, diff) 
res <- res[, row := seq_along(.I), by = .(id, time1)][row == 1]