【问题标题】:R dplyr select row of minimum date difference between two separate eventsR dplyr 选择两个单独事件之间的最小日期差异行
【发布时间】:2016-01-15 13:59:39
【问题描述】:

我正在处理一个包含大约 400 个独特主题的数据集。对于这个例子,我只会使用两个。您可以使用以下代码生成示例数据:

set.seed(100)
library(tidyr)
library(dplyr)
Subject<-c("A","A","A","A","A","A","B","B","B","B")
Event1<-c("01/01/2001","01/01/2001","01/01/2001","01/01/2001","09/09/2001","09/09/2001","09/09/2009","09/09/2009","09/09/2009","09/09/2009")

random.dates<-function(N,sd="2001-01-01",ed="2010-01-01"){
    sd<-as.Date(sd,"%Y-%m-%d")
    ed<-as.Date(ed,"%Y-%m-%d")
    dt<-as.numeric(difftime(ed,sd))
    ev<-sort(runif(N,0,dt))
    rt<-sd+ev
}
Event1<-as.Date(Event1,"%m/%d/%Y")
Event1
Event2<-print(random.dates(10))

df<-data.frame(Subject,Event1,Event2)
df

并产生接近这个输出输出的东西:

   Subject     Event1     Event2
1        A 2001-01-01 2001-05-04
2        A 2001-01-01 2001-09-24
3        A 2001-01-01 2002-10-22
4        A 2001-01-01 2003-02-25
5        A 2001-09-09 2007-07-16
6        A 2001-09-09 2008-04-06
7        B 2009-09-09 2008-07-12
8        B 2009-09-09 2008-07-24
9        B 2009-09-09 2009-04-01
10       B 2009-09-09 2009-09-11

在这种情况下,我有兴趣首先将独特的主题与独特的 Event1 进行分组,我可以轻松地做到这一点。从那里我需要为那个独特的 Subject-Event1 组合选择最接近 Event1 的 Event2,我真的需要帮助。对于此示例,这些数据应分解为 3 个不同的记录:

   Subject     Event1     Event2
1        A 2001-01-01 2001-05-04
2        A 2001-09-09 2008-04-06
3        B 2009-09-09 2009-09-11

我已经设计了一个解决方案来生成 Subject-Event1 组合的 3 条记录:

df2<-df
df2$SubEv<-paste(df2$Subject,df2$Event1)
df2$Event1<-NULL
df2$Subject<-NULL
df2$Event2<-NULL
df2<-unique(df2)
df2<-separate(df2,SubEv,c("Subject","Event1"),sep=" ")

从这里我只是迷失了如何让 R 从 df 中选择最接近 Event1 的 Event2 的日期。

我已经知道我的代码效率极低且草率(可能是因为我一开始就采用了方法)。我想知道如何做到这一点(老实说),如果有一种方法可以做到这一点,只需调用不到 10 行代码就可以了。

【问题讨论】:

  • 我认为您正在寻找(使用 dplyr):df %&gt;% group_by(Subject, Event1) %&gt;% slice(which.min(abs(Event1 - Event2))),但我没有看到与您相同的三个 Event2。
  • 轰隆隆!干得好,@Frank。我不知道您可以将两个不同的向量放入 group_by,我也不知道 slice。非常感谢!
  • 哦,我明白了:我的df 与你的不同,即使你设置了种子......也许你可以重新运行你的代码来验证你在那里打印的df
  • `主题Eve​​nt1 Event2`1 A 2001-01-01 2001-05-042 A 2001-09-09 2007-07-163 B 2009-09-09 2009-09-11
  • 好吧,很高兴它解决了您的问题。即使我不能完全复制你的例子,我也会写下来。

标签: r date grouping dplyr tidyr


【解决方案1】:

使用 dplyr:

library(dplyr)
df %>% 
     group_by(Subject, Event1) %>% 
     slice(which.min(abs(Event1 - Event2)))
#   Subject     Event1     Event2
#     (chr)     (date)     (date)
# 1       A 2001-01-01 2001-07-05
# 2       A 2001-09-09 2004-05-02
# 3       B 2009-09-09 2008-04-24

评论:

group_by 可以处理多个列。

slice 选择组内的行号。或者……

... %>% filter( row_number() == which.min(abs(Event1 - Event2)) )

对于平局,which.min 将返回第一个 min。详情请见?which.min


数据:当我运行 OP 的代码时,我得到 df 看起来像

   Subject     Event1     Event2
1        A 2001-01-01 2001-07-05
2        A 2001-01-01 2002-07-14
3        A 2001-01-01 2003-04-27
4        A 2001-01-01 2003-10-09
5        A 2001-09-09 2004-05-02
6        A 2001-09-09 2005-03-21
7        B 2009-09-09 2005-05-10
8        B 2009-09-09 2005-12-02
9        B 2009-09-09 2005-12-21
10       B 2009-09-09 2008-04-24

这解释了为什么我的结果与 OP 的预期结果不完全匹配。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-12
    • 1970-01-01
    • 2011-04-20
    • 1970-01-01
    • 2013-07-17
    相关资源
    最近更新 更多