我有一个水质样本数据集,我想根据质量控制样本的结果分配等级(Prelim_dql)。
我有两个不同的数据框。一个用于水质样品,一个用于QC结果。
水质样本分批分组。这个简化的示例版本有两个组(grp1和grp2)。
Group ID Result DateTime Prelim_dql
grp1 1 218.7 7/14/2009
grp1 2 1119.9 7/20/2009
grp1 3 128.1 7/27/2009
grp1 4 192.4 8/5/2009
grp1 5 524.7 8/18/2009
grp1 6 325.5 9/2/2009
grp2 7 19.2 7/13/2009
grp2 8 15.26 7/16/2009
grp2 9 14.58 8/13/2009
grp2 10 13.06 8/13/2009
grp2 11 12.56 10/12/2009
质量控制样本的简化版本如下所示:
Group QCID DateTime DQL
grp1 1 7/26/2009 A
grp1 2 7/29/2009 C
grp2 3 7/14/2009 A
grp2 4 9/10/2009 B
grp2 5 10/12/2009 A
我希望能够根据质量控制样本的日期范围分配样本结果等级。如果样本日期在第一个QC结果之前,那么我想从第一个QC结果中分配DQL。如果样本日期在两个QC结果之间,我想分配两个DQL中的较低者(A是最高等级,C是最低等级)。如果结果在最后一个QC结果之后,则从最后一个QC结果中分配DQL。
在这种情况下,我想得到这个结果:
Group ID Result DateTime Prelim_dql
grp1 1 218.7 7/14/2009 A
grp1 2 1119.9 7/20/2009 A
grp1 3 128.1 7/27/2009 C
grp1 4 192.4 8/5/2009 C
grp1 5 524.7 8/18/2009 C
grp1 6 325.5 9/2/2009 C
grp2 7 19.2 7/13/2009 A
grp2 8 15.26 7/16/2009 B
grp2 9 14.58 8/13/2009 B
grp2 10 13.06 8/13/2009 B
grp2 11 12.56 10/12/2009 A
我搜索过并搜索过,但我无法弄清楚如何做到这一点。有什么想法吗?
答案 0 :(得分:0)
使用sqldf
和dplyr
包可以实现一个解决方案。
请注意,列Group
的名称已更改为Grp
,因为Group
不是sqldf
中的有效名称。
方法:
修改QC
数据框,以便每行定义适用的日期范围,并添加一列以指示该行包含max
组的日期。将此修改后的QC
加入samples
即可获得所需的结果。
#Data to be used are
samples <- read.table(text = "Grp ID Result DateTime
grp1 1 218.7 7/14/2009
grp1 2 1119.9 7/20/2009
grp1 3 128.1 7/27/2009
grp1 4 192.4 8/5/2009
grp1 5 524.7 8/18/2009
grp1 6 325.5 9/2/2009
grp2 7 19.2 7/13/2009
grp2 8 15.26 7/16/2009
grp2 9 14.58 8/13/2009
grp2 10 13.06 8/13/2009
grp2 11 12.56 10/12/2009", header = T, stringsAsFactors = F)
samples$DateTime = as.POSIXct(samples$DateTime, format = "%m/%d/%Y")
QC <- read.table(text = "Grp QCID DateTime DQL
grp1 1 7/26/2009 A
grp1 2 7/29/2009 C
grp2 3 7/14/2009 A
grp2 4 9/10/2009 B
grp2 5 10/12/2009 A", header = T, stringsAsFactors = F)
QC$DateTime = as.POSIXct(QC$DateTime, format = "%m/%d/%Y")
library(dplyr)
library(sqldf)
# Add a column for end of applicable day of a DQL using lag
# Add another column to indicate a row contains Max date for that group
QC_Mod <- QC %>% group_by(Grp) %>%
mutate(ApplicableAfter = lag(DateTime)) %>%
mutate(IsMaxDate = ifelse(DateTime == max(DateTime),1,0)) %>%
as.data.frame()
# Join the data.frames to find DQL value
sqldf("SELECT samples.Grp, samples.ID, samples.Result, samples.DateTime , QC_Mod.DQL as Prelim_dql
FROM samples, QC_Mod
WHERE samples.Grp == QC_Mod.Grp AND
(
(samples.DateTime <= QC_Mod.DateTime AND QC_Mod.ApplicableAfter IS NULL) OR
(QC_Mod.ApplicableAfter IS NOT NULL AND samples.DateTime > QC_Mod.ApplicableAfter AND samples.DateTime <= QC_Mod.DateTime) OR
(samples.DateTime > QC_Mod.DateTime AND QC_Mod.IsMaxDate == 1)
)")
# Result
# Grp ID Result DateTime Prelim_dql
# 1 grp1 1 218.70 2009-07-14 A
# 2 grp1 2 1119.90 2009-07-20 A
# 3 grp1 3 128.10 2009-07-27 C
# 4 grp1 4 192.40 2009-08-05 C
# 5 grp1 5 524.70 2009-08-18 C
# 6 grp1 6 325.50 2009-09-02 C
# 7 grp2 7 19.20 2009-07-13 A
# 8 grp2 8 15.26 2009-07-16 B
# 9 grp2 9 14.58 2009-08-13 B
# 10 grp2 10 13.06 2009-08-13 B
# 11 grp2 11 12.56 2009-10-12 A