如何按组分组获取具有最早时间戳的数据框?

时间:2014-12-01 20:12:12

标签: r dplyr

df <- data.frame(group=c(1,2,4,2,1,4,2,3,3),
             ts=c("2014-02-13","2014-06-01","2014-02-14","2014-02-11","2013-02-01","2014-02-02","2014-03-21","2014-12-01","2014-02-11"),
             letter=letters[1:9])
df$ts <- as.Date(df$ts,format='%Y-%m-%d')

我想找到一个操作,它将产生包含每组最小时间戳的完整行,在这种情况下,

group         ts letter
    1 2013-02-01      e
    4 2014-02-02      f
    2 2014-02-11      d
    3 2014-02-11      i

快速而肮脏(和缓慢)的基础R解决方案

dfo <- data.frame(df[order(df$ts,decreasing=F),],index=seq(1:nrow(df)))
mins <- tapply(dfo$index,dfo$group,min)
dfo[dfo$index %in% mins,]

直观地说,我认为如果有一种方法可以按组添加订单索引,那么我可以过滤到该列的值为1的位置,但我不确定如何在没有批次的情况下执行它子集化和重新加入。

3 个答案:

答案 0 :(得分:3)

您可以使用dplyr

library(dplyr)
group_by(df, group) %>% summarise(min = min(ts), letter = letter[which.min(ts)]) 
#   group        min letter
# 1     1 2013-02-01      e
# 2     2 2014-02-11      d
# 3     3 2014-02-11      i
# 4     4 2014-02-02      f

您还可以slice排名的行

group_by(df, group) %>% 
    mutate(rank = row_number(ts)) %>% 
    arrange(rank) %>%
    slice(1)

答案 1 :(得分:3)

这是一个data.table解决方案。您似乎希望ts而不是group的结果订单。就是这样。

library(data.table)
setDT(df)[,.SD[which.min(ts)],by=group][order(ts)]
#    group         ts letter
# 1:     1 2013-02-01      e
# 2:     4 2014-02-02      f
# 3:     2 2014-02-11      d
# 4:     3 2014-02-11      i

答案 2 :(得分:0)

这里是使用基础R的单行。

df[sapply(split(df,df$group), function(x) row.names(x)[which.min(x$ts)] ),]

打破一些:

list.by.group <- split(df,df$group)
#a vector of the row names corresponding to the earliest date in each group
names.of.which.min <- sapply(list.by.group, function(x) row.names(x)[which.min(x$ts)])
#subset the data frame by row name
df[names.of.which.min,]