【问题标题】:Compare date by group in two data frames in R在R中的两个数据框中按组比较日期
【发布时间】:2019-03-07 12:37:02
【问题描述】:

我有一个按 id 包含事件日期的数据框:

data.frame(id = c("a", "a", "a", "d", "d"),
           date = as.Date(c("2018-01-03", "2018-02-02", "2018-02-22", "2018-02-13", "2018-05-01")))

  id       date
1  a 2018-01-03
2  a 2018-02-02
3  a 2018-02-22
4  d 2018-02-13
5  d 2018-05-01

另一个包含 id 开始和结束的句点:

data.frame(id = c("a", "a", "d", "d", "d", "d"),
           start = as.Date(c("2018-01-15", "2018-01-30", "2018-03-01", "2018-02-01", "2018-04-02", "2018-03-19")),
           end = as.Date(c("2018-01-18", "2018-02-10", "2018-03-03", "2018-04-22", "2018-05-23", "2018-08-29")))

  id      start        end
1  a 2018-01-15 2018-01-18
2  a 2018-01-30 2018-02-10
3  d 2018-03-01 2018-03-03
4  d 2018-02-01 2018-04-22
5  d 2018-04-02 2018-05-23
6  d 2018-03-19 2018-08-29

对于每个id,我需要统计第一个数据帧中每个日期所属的第二个数据帧的周期数。

我想要的数据框是:

  id       date n
1  a 2018-01-03 0    # does not belong to any period
2  a 2018-02-02 1    # belongs to [2018-01-30,2018-02-10]
3  a 2018-02-22 0    # does not belong to any period
4  d 2018-02-13 1    # belongs to [2018-02-01,2018-04-22]
5  d 2018-05-01 2    # belongs to [2018-04-02,2018-05-23] and [2018-03-19,2018-08-29]

我的问题不在于日期比较和结果求和。我的问题是关于在每个 id 组内执行这些分析。我想有一种方法可以使用split 和/或apply 系列,但我没有找到方法。

如何在基础 R 中做到这一点?我在一个只能访问基础 R 的限制性环境中工作。

【问题讨论】:

    标签: r date dataframe compare


    【解决方案1】:

    基础 r 方法

    temp <- subset( merge(df1, df2), date >= start & date <= end, select = "date" )
    df1$n <- sapply( df1$date, function(x) length( temp$date[ temp$date == x ] ))
    
    #   id       date n
    # 1  a 2018-01-03 0
    # 2  a 2018-02-02 1
    # 3  a 2018-02-22 0
    # 4  d 2018-02-13 1
    # 5  d 2018-05-01 2
    

    【讨论】:

    • 非常感谢这个简单有效的回答!
    • 最后,虽然您的方法适用于我的示例,但它不适用于我的真实数据,但这是因为我的示例不够好。实际上,我的示例缺少一个案例是两个相同的date 来自df1 中的两个不同的id 都属于df2 中的一个句点。可以通过使用df1[df1$date == "2018-02-13", "date"] &lt;- "2018-02-02" 更改我的原始示例中的日期来获得这种情况。在这个新示例中,n 对于 2018-02-02 都是 2 而不是 1,因为在 id 上没有过滤器。 Stéphane Laurent 的方法在这种情况下有效,因为我们可以过滤 date + idaggregate
    【解决方案2】:

    另一种基本 R 方法:

    dates <- data.frame(id = c("a", "a", "a", "d", "d"),
                        date = as.Date(c("2018-01-03", "2018-02-02", "2018-02-22", "2018-02-13", "2018-05-01")))
    periods <- data.frame(id = c("a", "a", "d", "d", "d", "d"),
                          start = as.Date(c("2018-01-15", "2018-01-30", "2018-03-01", "2018-02-01", "2018-04-02", "2018-03-19")),
                          end = as.Date(c("2018-01-18", "2018-02-10", "2018-03-03", "2018-04-22", "2018-05-23", "2018-08-29")))
    
    df <- transform(merge(dates, periods), belongs = date >= start & date <= end)
    
    aggregate(belongs ~ date + id, data = df, sum)
    #         date id belongs
    # 1 2018-01-03  a       0
    # 2 2018-02-02  a       1
    # 3 2018-02-22  a       0
    # 4 2018-02-13  d       1
    # 5 2018-05-01  d       2
    

    或者使用data.table:

    library(data.table)
    dt <- as.data.table(merge(dates, periods))
    dt[, .(n = sum(date >= start & date <= end)), by=c("id","date")]
    #    id       date n
    # 1:  a 2018-01-03 0
    # 2:  a 2018-02-02 1
    # 3:  a 2018-02-22 0
    # 4:  d 2018-02-13 1
    # 5:  d 2018-05-01 2
    

    【讨论】:

    • 非常感谢这个简单有效的回答!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-05-05
    • 2015-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-15
    相关资源
    最近更新 更多