繁体   English   中英

保留数据框中每个ID的最新日期

[英]Retain only the most recent date for every ID in a data frame

我在R中有一个数据框,其中的行代表事件,一列是事件的日期。 事件发生的事件由ID列描述。 因此,对于每个ID,都有多个条目。

如何过滤数据帧,以便仅保留每个ID的最新事件? ID是整数,日期格式为mm/dd/yyyy

你可以试试

library(dplyr)
df %>% 
  group_by(ID) %>%
  slice(which.max(as.Date(date, '%m/%d/%Y')))

数据

df <- data.frame(ID= rep(1:3, each=3), date=c('02/20/1989',
'03/14/2001', '02/25/1990',  '04/20/2002', '02/04/2005', '02/01/2008',
'08/22/2011','08/20/2009', '08/25/2010' ), stringsAsFactors=FALSE)

对于任何解决方案,您最好先更正日期变量,如@akrun所示:

df$date <- as.Date(df$date, '%m/%d/%Y')

基数R

df[
  tapply(1:nrow(df),df$ID,function(ii) ii[which.max(df$date[ii])])
,]

这将使用行号的选择来对数据进行子集化。 您可以通过单独运行中间行(在[]之间)来查看选择。

数据表

类似于@ rawr's:

require(data.table)
DT <- data.table(df)

unique(DT[order(date)], by="ID", fromLast=TRUE)
# or
unique(DT[order(-date)], by="ID")

或者您可以订购日期和

df <- data.frame(ID= rep(1:3, each=3), date=c('02/20/1989',
                                              '03/14/2001', '02/25/1990',  '04/20/2002', '02/04/2005', '02/01/2008',
                                              '08/22/2011','08/20/2009', '08/25/2010' ), stringsAsFactors=FALSE)

df$date <- as.Date(df$date, '%m/%d/%Y')

## make sure to order by both `ID` and `date` as Frank mentions in comments
## since the dates may be overlapping among IDs

df <- df[with(df, order(ID, date)), ]

1)选择最后一个

df[cumsum(table(df$ID)), ]

#   ID       date
# 2  1 2001-03-14
# 6  2 2008-02-01
# 7  3 2011-08-22

2)或删除重复项

df[!duplicated(df$ID, fromLast = TRUE), ]

#   ID       date
# 2  1 2001-03-14
# 6  2 2008-02-01
# 7  3 2011-08-22

@akrun带给您的数据

这可能是一个性格缺陷,但我有时会拒绝选择新包装。 “ base R”功能通常可以胜任。 在这种情况下,由于ave函数返回了用于逻辑测试的字符值(我仍然不了解),因此我偶然创建了一个好的解决方案,因此我认为dplyr软件包的dplyr显示出来。 所以我认为dplyr是真正的宝石。 如果可以的话,我想坚持认为,在任何投票之前都必须有对akrun答案的投票。 (很难相信尚未在SO上被问及得到答案。)

无论如何:

> df[ as.logical(
        ave(df$date, df$ID, FUN=function(d) as.Date(d , '%m/%d/%Y') == 
                                             max(as.Date(d, '%m/%d/%Y'))))
      , ]
  ID       date
2  1 03/14/2001
6  2 02/01/2008
7  3 08/22/2011

我认为这应该工作(失败):

> df[ ave(df$date, df$ID, FUN=function(d) as.Date(d , '%m/%d/%Y') ==max(as.Date(d, '%m/%d/%Y'))) , ]
     ID date
NA   NA <NA>
NA.1 NA <NA>
NA.2 NA <NA>
NA.3 NA <NA>
NA.4 NA <NA>
NA.5 NA <NA>
NA.6 NA <NA>
NA.7 NA <NA>
NA.8 NA <NA>

这是另一个毫无意外地首次使用的基本R解决方案:

> do.call( rbind, by(df, df$ID, function(d) d[ which.max(as.Date(d$date, '%m/%d/%Y')), ] ) )
  ID       date
1  1 03/14/2001
2  2 02/01/2008
3  3 08/22/2011

这是@rawr从有序子集中获取最后一个的想法的启发:

> do.call( rbind, by(df, df$ID, function(d) tail( d[ order(as.Date(d$date, '%m/%d/%Y')), ] ,1)) )
  ID       date
1  1 03/14/2001
2  2 02/01/2008
3  3 08/22/2011

没有plyr我从未处理过R中的任何数据!

library(plyr)
ddply(df, .(ID), summarize, most_recent = max(as.Date(date, '%m/%d/%Y')))

   ID most_recent
1  1  2001-03-14
2  2  2008-02-01
3  3  2011-08-22

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM