如何根据R中行之间的日期差异筛选行?

如何根据R中行之间的日期差异筛选行?,r,dplyr,R,Dplyr,在每个id中,我希望保留至少间隔91天的行。在下面我的数据框df中,id=1有5行,id=2有1行 对于id=1,我只保留第一、第三和第五行 这是因为如果我们比较第一个日期和第二个日期,它们相差32天。所以,删除第二个日期。我们继续比较第一个和第三个日期,它们相差152天。所以,我们保持第三次约会 现在,我们不使用第一个日期作为参考,而是使用第三个日期。第三天和第四天相差61天。所以,删除第四次约会。我们继续比较第3天和第5天,它们相差121天。所以,我们保持第五次约会 最后,我们保留的日期是第

在每个
id
中,我希望保留至少间隔91天的行。在下面我的数据框
df
中,
id=1
有5行,
id=2
有1行

对于
id=1
,我只保留第一、第三和第五行

这是因为如果我们比较第一个日期和第二个日期,它们相差32天。所以,删除第二个日期。我们继续比较第一个和第三个日期,它们相差152天。所以,我们保持第三次约会

现在,我们不使用第一个日期作为参考,而是使用第三个日期。第三天和第四天相差61天。所以,删除第四次约会。我们继续比较第3天和第5天,它们相差121天。所以,我们保持第五次约会

最后,我们保留的日期是第一天、第三天和第五天。至于
id=2
,只有一行,所以我们保留这一行。所需结果显示在
dfnew

df <- read.table(header = TRUE, text = "
id  var1  date        
 1  A     2006-01-01 
 1  B     2006-02-02 
 1  C     2006-06-02 
 1  D     2006-08-02 
 1  E     2007-12-01 
 2  F     2007-04-20 
",stringsAsFactors=FALSE)

dfnew <- read.table(header = TRUE, text = "
id  var1  date        
 1  A     2006-01-01 
 1  C     2006-06-02 
 1  E     2007-12-01 
 2  F     2007-04-20 
",stringsAsFactors=FALSE)

然而,我不知道如何从这里继续下去。我应该继续使用
过滤器
功能还是
切片
?如果是这样,怎么做?

这里有一个尝试,在
data.table
中使用滚动联接,我认为这应该是有效的

library(data.table)
# Set minimum distance
mindist <- 91L 
# Make sure it is a real Date
setDT(df)[, date := as.IDate(date)] 
# Create a new column with distance + 1 to roll join too
df[, date2 := date - (mindist + 1L)] 
# Perform a rolling join per each value in df$date2 that has atleast 91 difference from df$date
unique(df[df, on = c(id = "id", date = "date2"), roll = -Inf], by = c("id", "var1"))
#    id var1       date      date2 i.var1     i.date
# 1:  1    A 2005-10-01 2005-10-01      A 2006-01-01
# 2:  1    C 2006-03-02 2006-03-02      C 2006-06-02
# 3:  1    E 2007-08-31 2007-08-31      E 2007-12-01
# 4:  2    F 2007-01-18 2007-01-18      F 2007-04-20
库(data.table)
#设置最小距离

mindist使用
dplyr
中的
slice
的另一种方法是定义以下递归函数:

library(dplyr)
f <- function(d, ind=1) {
  ind.next <- first(which(difftime(d,d[ind], units="days") > 90))
  if (is.na(ind.next))
    return(ind)
  else
    return(c(ind, f(d,ind.next)))
}
此函数的使用假定
date
列按每个
id
组的升序排序。如果没有,我们可以在切片之前对日期进行排序。不确定这是否有效,也不确定R中递归调用的危险性。希望David Arenburg或其他人能够对此发表评论


正如David Arenburg所建议的,最好先将
date
转换为日期类,而不是按组:

result <- df %>% mutate(date=as.Date(date, format="%Y-%m-%d")) %>%
                 group_by(id) %>% slice(f(date))
##Source: local data frame [4 x 3]
##Groups: id [2]
##
##     id  var1       date
##  <int> <chr>     <date>
##1     1     A 2006-01-01
##2     1     C 2006-06-02
##3     1     E 2007-12-01
##4     2     F 2007-04-20
result%mutate(date=as.date(date,format=“%Y-%m-%d”))%%>%
分组依据(id)%>%切片(f(日期))
##来源:本地数据帧[4 x 3]
##组别:id[2]
##
##id var1日期
##        
##11A 2006-01-01
##21c 2006-06-02
##3 1 E 2007-12-01
##4.2 F 2007-04-20

可以先转换成
日期
类,而不是通过group@DavidArenburg:谢谢,非常感谢您的评论。我做了编辑。嗨@aichao这个答案很有帮助。我有一个数据集,我想过滤行,这样的日期是365天间隔(+/-90天)从以前的。此日期必须最接近第365天标记。我对您的代码进行了如下修改:
f需要在切片之前先进行安排
result <- df %>% group_by(id) %>% slice(f(as.Date(date, format="%Y-%m-%d")))
##Source: local data frame [4 x 3]
##Groups: id [2]
##
##     id  var1       date
##  <int> <chr>      <chr>
##1     1     A 2006-01-01
##2     1     C 2006-06-02
##3     1     E 2007-12-01
##4     2     F 2007-04-20
result <- df %>% mutate(date=as.Date(date, format="%Y-%m-%d")) %>%
                 group_by(id) %>% slice(f(date))
##Source: local data frame [4 x 3]
##Groups: id [2]
##
##     id  var1       date
##  <int> <chr>     <date>
##1     1     A 2006-01-01
##2     1     C 2006-06-02
##3     1     E 2007-12-01
##4     2     F 2007-04-20