【问题标题】:Subset R data frame based on group-level values基于组级值的子集 R 数据框
【发布时间】:2016-06-30 05:48:06
【问题描述】:

我有一个带有 ID 的数据框 (df1),日期按 (1) ID 和 (2) 日期升序排序:

ID____Date
1_____1990-01-01
1_____1991-01-01
1_____1992-01-01
1_____1993-01-01
2_____1990-01-01
2_____1991-01-01
3_____1990-01-01
3_____1991-01-01
3_____1992-01-01

我想根据来自以下数据框 (df2) 的组级别值对上述数据框进行子集化:

ID____Date
1_____1993-01-01
2_____1990-01-01
3_____1991-01-01

子集条件:选择df1中特定ID的所有行,其日期小于或等于(<=)df2中对应ID的日期。

在上面的例子中,期望的输出是:

ID____Date
1_____1991-01-01
1_____1992-01-01
1_____1993-01-01
2_____1990-01-01
3_____1990-01-01
3_____1991-01-01

【问题讨论】:

    标签: r


    【解决方案1】:

    我们可以使用data.table。将“data.frame”转换为“data.table”(setDT(df1)),与“df2”on“ID”列连接,将“Date”小于或等于“i​​.Date”的行作为子集',并将 (:=) 'i.Date' 赋值为 NULL。

    library(data.table)
    setDT(df1)[df2, on = 'ID'][Date <= i.Date][, i.Date := NULL]
    

    或者这可以一步完成

    setDT(df1)[df2, .SD[Date <= i.Date], on = 'ID', by = .EACHI]
    #   ID       Date
    #1:  1 1990-01-01
    #2:  1 1991-01-01
    #3:  1 1992-01-01
    #4:  1 1993-01-01
    #5:  2 1990-01-01
    #6:  3 1990-01-01
    #7:  3 1991-01-01
    

    或者

    setDT(df1)[df2, .SD[Date <= i.Date] ,on = 'ID']
    

    我们也可以使用base R来做到这一点

    df1[df1$Date <= df2$Date[match(df1$ID, df2$ID)],]
    #  ID       Date
    #1  1 1990-01-01
    #2  1 1991-01-01
    #3  1 1992-01-01
    #4  1 1993-01-01
    #5  2 1990-01-01
    #7  3 1990-01-01
    #8  3 1991-01-01
    

    【讨论】:

    • Base R 解决方案的运行速度比 data.table 和 sqldf 快得多。在 1 秒内处理 200 万行,而 sqldf 为 20 秒,data.table 为 2 秒
    • @NaveenMathew 是因为我们没有加入,而是使用match 来获取索引。它要快得多。
    【解决方案2】:

    也可以使用sqldf 来完成:

    library(sqldf)
    sqldf("select a.* from df1 a, df2 b where a.Date <= b.Date AND a.ID = b.ID" )
    

    【讨论】:

      猜你喜欢
      • 2020-07-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多