【问题标题】:Merge 2 dataframes with conditions on datetimes and get the counts for passfails将 2 个数据帧与日期时间条件合并并获取通过失败的计数
【发布时间】:2017-03-15 21:13:38
【问题描述】:

我有 2 个这样的数据框

df1

ID <- c("ID001","ID001","ID002","ID003")
Type <- c("A","A","B","A")
Measurement <- c("Length","Breadth","Length","Length")
When <- c("2016-09-09 06:00:13", "2016-09-19 09:13:10", "2016-10-13 11:45:14", "2016-10-29 11:56:00")

df1 <- data.frame(ID,Type,Measurement,When)

df2

    ID <- c("ID001","ID001","ID001","ID001","ID001",
            "ID002","ID002","ID002","ID002","ID002")
    Type <- c("A","A","A","A","A",
              "B","B","B","B","B")
    Measurement <- c("Length","Length","Length","Length","Length",
                     "Length","Length","Length","Length","Length")
    Datetime <- c("2016-09-09 01:00:13", "2016-09-09 04:00:13", "2016-09-09 09:00:13", "2016-09-09 21:00:13","2016-09-09 23:00:13",
                  "2016-10-13 10:45:14", "2016-10-13 11:15:14", "2016-10-13 11:48:14", "2016-10-13 11:55:14","2016-10-13 21:45:14")
    PassFail <- c("Pass","Fail","Pass","Fail","Pass",
                  "Fail","Fail","Pass","Pass","Pass")

    df2 <- data.frame(ID,Type,Measurement,Datetime,PassFail)

我正在尝试合并这 2 个数据帧以获取通过次数和失败次数,仅用于 df2 中的“日期时间”大于 df1 中的“WHEN”的测量。

我想要的输出是

    ID Type Measurement                When PassCount FailCount
  ID001    A      Length 2016-09-09 06:00:13         2         1
  ID002    B      Length 2016-10-13 11:45:14         3         0

我尝试使用 sqldf 来获得这个

library(sqldf)
df3<-sqldf("SELECT L.*, r.Datetime, r.PASSFAIL
            FROM df1 as L
            LEFT JOIN df2 as r
            ON L.ID=r.ID
            AND L.Type=r.Type
            AND L.Measurement=r.Measurement
            WHERE r.Datetime > L.When
            ORDER BY L.When")

我没有成功获得输出。有人能指出我正确的方向吗?我也想要一个快速合并解决方案,因为我想将它应用到更大的数据集。

【问题讨论】:

  • 请使用日期时间格式,而不是因素。
  • dplyr 有left_join、filter、group_by、summary等功能应该可以解决

标签: r dataframe dplyr


【解决方案1】:

使用 data.table,非 equi 连接似乎可以工作:

library(data.table)
setDT(df1)[, When := as.POSIXct(When)]
setDT(df2)[, Datetime := as.POSIXct(Datetime)]

df2[df1, on=.(ID, Datetime > When), if (.N > 0L) as.list(table(PassFail)), by=.EACHI]

#       ID            Datetime Fail Pass
# 1: ID001 2016-09-09 06:00:13    1    2
# 2: ID002 2016-10-13 11:45:14    0    3

如果您希望df1 的每一行都有一行,请删除if 子句。

将计数作为列添加到df1

df1[, levels(df2$PassFail) := 
  df2[df1, on=.(ID, Datetime > When), as.list(table(PassFail)), by=.EACHI][, !c("ID","Datetime")]
]

【讨论】:

  • 绝妙的解决方案。我花了一些时间来理解你的代码,但现在很有意义。非常感谢。我只是将它应用于更大的数据集,它就像魅力一样。
猜你喜欢
  • 2018-06-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-30
  • 1970-01-01
  • 2019-08-10
  • 2018-02-18
  • 2017-12-30
相关资源
最近更新 更多