设置数据
首先设置输入数据帧。我们创建两个版本的数据帧:A 和 B 只使用字符列作为时间,At 和 Bt 使用 chron 包 "times" 类作为时间(比 @987654328 有优势@class 可以加减):
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
实际上可以不使用"times" 类,方法是使用sqlite 的strftime 函数在sqlite 中使用字符串执行所有时间计算。不幸的是,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 语句。