2015-01-28 3 views
5

Ситуацияг - выбрать последние п вхождений для каждой группы

У меня есть кадр данных 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 

?

Я попытался комбинации

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

не радость.

ответ

6

Вы можете попробовать 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)) 
+0

узнать что-то новое каждый день; 'do()' - спасибо. – tospig

+0

@tospig 'do' полезен, но я думаю, что' slice' будет быстрее. – akrun

+0

Я получаю сообщение 'не удалось найти функцию slice' – tospig

4

Использование 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 

Мы заказ по person и затем наperson и выберите последние две строки из подмножества данных .SD для каждой группы.

+1

По какой-то причине я не читал синтаксис 'data.table'. Может быть, мне следует начать учиться. – tospig

+1

Вы можете начать с [этих виньет] (https://github.com/Rdatatable/data.table/issues/944). – Arun

3

Поскольку вы заказываете данные от лица и дату (т.е. вы хотите 2 последние даты на человека), вы также можете использовать top_n() в dplyr:

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 

Или, если вы уже заказать его, вы могли бы организовать его по-другому, прежде чем использовать срез:

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 

См here для ориентира подобного вопроса.

Смежные вопросы