根据第二个数据帧的日期

时间:2018-02-07 22:20:51

标签: r datetime

我有一个水质样本数据集,我想根据质量控制样本的结果分配等级(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

我搜索过并搜索过,但我无法弄清楚如何做到这一点。有什么想法吗?

1 个答案:

答案 0 :(得分:0)

使用sqldfdplyr包可以实现一个解决方案。 请注意,列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