簡體   English   中英

合並記錄隨時間間隔

[英]Merge Records Over Time Interval

首先讓我說這個問題與R(統計編程語言)有關,但我對其他環境提出了直截了當的建議。

目標是將數據框架(df)A的結果合並到df B中的子元素。這是一對多的關系,但是,這是扭曲 ,一旦記錄與鍵匹配,它們也必須匹配特定的框架開始時間和持續時間給出的時間。

例如,df A中的一些記錄:

    OBS ID StartTime Duration Outcome 
    1   01 10:12:06  00:00:10 Normal
    2   02 10:12:30  00:00:30 Weird
    3   01 10:15:12  00:01:15 Normal
    4   02 10:45:00  00:00:02 Normal

從df B:

    OBS ID Time       
    1   01 10:12:10  
    2   01 10:12:17  
    3   02 10:12:45  
    4   01 10:13:00  

合並的預期結果將是:

    OBS ID Time     Outcome  
    1   01 10:12:10 Normal 
    3   02 10:12:45 Weird 

期望的結果:數據框B與結果合並在A中。通知觀察2和4被刪除,因為盡管它們匹配A中記錄的ID,但它們不屬於給定的任何時間間隔內。

是否可以在R中執行此類操作,您將如何開始? 如果沒有,你能建議一個替代工具嗎?

設置數據

首先設置輸入數據幀。 我們創建了兩個版本的數據框: AB只使用字符列表示時間, AtBt使用chron包"times"類表示時間(這比"character"類更有優勢,可以添加和減去他們):

LinesA <- "OBS ID StartTime Duration Outcome 
    1   01 10:12:06  00:00:10 Normal
    2   02 10:12:30  00:00:30 Weird
    3   01 10:15:12  00:01:15 Normal
    4   02 10:45:00  00:00:02 Normal"

LinesB <- "OBS ID Time       
    1   01 10:12:10  
    2   01 10:12:17  
    3   02 10:12:45  
    4   01 10:13:00"

A <- At <- read.table(textConnection(LinesA), header = TRUE, 
               colClasses = c("numeric", rep("character", 4)))
B <- Bt <- read.table(textConnection(LinesB), header = TRUE, 
               colClasses = c("numeric", rep("character", 2)))

# in At and Bt convert times columns to "times" class

library(chron) 

At$StartTime <- times(At$StartTime)
At$Duration <- times(At$Duration)
Bt$Time <- times(Bt$Time)

sqldf與時間類

現在我們可以使用sqldf包執行計算。 我們使用method="raw" (它沒有為輸出分配類)所以我們必須將"times"類分配給輸出"Time"列自己:

library(sqldf)

out <- sqldf("select Bt.OBS, ID, Time, Outcome from At join Bt using(ID)
   where Time between StartTime and StartTime + Duration",
   method = "raw")

out$Time <- times(as.numeric(out$Time))

結果是:

> out
      OBS ID     Time Outcome
1   1 01 10:12:10  Normal
2   3 02 10:12:45   Weird

使用sqldf的開發版本,可以在不使用method="raw" ,並且"Time"列將通過sqldf類賦值啟發式自動設置為"times"類:

library(sqldf)
source("http://sqldf.googlecode.com/svn/trunk/R/sqldf.R") # grab devel ver 
sqldf("select Bt.OBS, ID, Time, Outcome from At join Bt using(ID)
    where Time between StartTime and StartTime + Duration")

sqldf與字符類

它實際上可以通過在sqlite中使用sqlite的strftime函數執行字符串中的所有時間計算來使用"times"類。 不幸的是,SQL語句涉及更多:

sqldf("select B.OBS, ID, Time, Outcome from A join B using(ID)
    where strftime('%s', Time) - strftime('%s', StartTime)
       between 0 and strftime('%s', Duration) - strftime('%s', '00:00:00')")

編輯:

一系列修改語法的編輯,添加了額外的方法並修復/改進了read.table語句。

編輯:

簡化/改進了最終的sqldf語句。

這是一個例子:

# first, merge by ID
z <- merge(A[, -1], B, by = "ID")

# convert string to POSIX time
z <- transform(z,
  s_t = as.numeric(strptime(as.character(z$StartTime), "%H:%M:%S")),
  dur = as.numeric(strptime(as.character(z$Duration), "%H:%M:%S")) - 
    as.numeric(strptime("00:00:00", "%H:%M:%S")),
  tim = as.numeric(strptime(as.character(z$Time), "%H:%M:%S")))

# subset by time range
subset(z, s_t < tim & tim < s_t + dur)

輸出:

  ID StartTime Duration Outcome OBS     Time        s_t dur        tim
1  1  10:12:06 00:00:10  Normal   1 10:12:10 1321665126  10 1321665130
2  1  10:12:06 00:00:10  Normal   2 10:12:15 1321665126  10 1321665135
7  2  10:12:30 00:00:30   Weird   3 10:12:45 1321665150  30 1321665165

OBS#2看起來在范圍內。 是否有意義?

將兩個data.frames與merge()在一起。 然后使用條件time >= startTime & time <= startTime + Duration或任何對你有意義的規則, subset()結果data.frame。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM