r - 选择每个分组的最后n个出现项

6

情况

我有一个数据框 df:

df <- structure(list(person = structure(c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 
    3L, 3L), .Label = c("pA", "pB", "pC"), class = "factor"), date = structure(c(16071, 
    16102, 16130, 16161, 16071, 16102, 16130, 16071, 16102), class = "Date")), .Names = c("person", 
    "date"), row.names = c(NA, -9L), class = "data.frame")

> df
  person       date
1     pA 2014-01-01
2     pA 2014-02-01
3     pA 2014-03-01
4     pA 2014-04-01
5     pB 2014-01-01
6     pB 2014-02-01
7     pB 2014-03-01
8     pC 2014-01-01
9     pC 2014-02-01

问题

如何按日期排序选择每个人的最后2个(或“n”个)条目,以便得到结果数据框df1

> df1
  person       date
1     pA 2014-03-01
2     pA 2014-04-01
3     pB 2014-02-01
4     pB 2014-03-01
5     pC 2014-01-01
6     pC 2014-02-01

?

I've tried combinations of

library(dplyr)
df1 <- df %>%
    group_by(person) %>% 
    select(tail(df, 2))

没有欢乐。
3个回答

7
您可以尝试使用 slice 函数。
library(dplyr)
df %>% 
    group_by(person) %>% 
    arrange(date, person) %>%
    slice((n()-1):n())
#  person       date
#1     pA 2014-03-01
#2     pA 2014-04-01
#3     pB 2014-02-01
#4     pB 2014-03-01
#5     pC 2014-01-01
#6     pC 2014-02-01

或者在最后一步的位置进行替换。
   do(tail(., 2))

@tospig do很有用,但我认为slice更快。 - akrun
1
我正在使用 dplyr_0.4.0。你用的是哪个版本的 dplyr? - akrun
啊,是的,我之前用的是 0.2 版本 - 现在已经更新到了 0.4.1 版本,现在可以正常工作了。 - tospig
而且在我的实际数据集(1600行x 16个变量)上,“切片”更快。 - tospig

6

使用data.table

setDT(df)[order(person), tail(.SD, 2L), by=person]
#    person       date
# 1:     pA 2014-03-01
# 2:     pA 2014-04-01
# 3:     pB 2014-02-01
# 4:     pB 2014-03-01
# 5:     pC 2014-01-01
# 6:     pC 2014-02-01

我们按照人员排序,然后按人员分组,并选择每个组的数据子集.SD中的最后两行。


1
由于某些原因,我一直没有学习 data.table 语法。也许我应该开始学习了。 - tospig
1
你可以从这些示例开始。 - Arun

3

如果您想按人员和日期排序数据(即想要每个人最近的两个日期),您也可以在dplyr中使用top_n()

df %>% group_by(person) %>% top_n(2, date)
#Source: local data frame [6 x 2]
#Groups: person
#
#  person       date
#1     pA 2014-03-01
#2     pA 2014-04-01
#3     pB 2014-02-01
#4     pB 2014-03-01
#5     pC 2014-01-01
#6     pC 2014-02-01

或者,如果你已经订购了它,你可以在使用slice之前将其安排好其他方式:

df %>% arrange(person, desc(date)) %>% group_by(person) %>% slice(1:2)
#Source: local data frame [6 x 2]
#Groups: person
#
#  person       date
#1     pA 2014-04-01
#2     pA 2014-03-01
#3     pB 2014-03-01
#4     pB 2014-02-01
#5     pC 2014-02-01
#6     pC 2014-01-01

请参考这里的类似问题的基准测试结果。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接