Как выбрать последнее N наблюдение из каждой группы в dplyr dataframe? - PullRequest
0 голосов
/ 01 января 2019

С учетом кадра данных:

df <- structure(list(a = c(1, 1, 1, 2, 2, 2, 3, 3, 4, 4), b = c(34, 
343, 54, 11, 55, 62, 59, -9, 0, -0.5)), row.names = c(NA, -10L
), class = c("tbl_df", "tbl", "data.frame"))

Я хочу взять последние N наблюдений / строк из каждой группы:

df %>% 
dplyr::group_by(a) %>% 
dplyr::last(2)

Дает мне неправильные результаты.

Iхотите, чтобы это было:

a   b
1 343
1  54
2  55
2  62
3  59
3  -9
4   0
4  -0.5

Пожалуйста, сообщите, что здесь не так?

Я получаю ошибку:

Ошибка в заказе (order_by) [[n]]: нижний индекс вне границ

Ответы [ 4 ]

0 голосов
/ 01 января 2019

try tail (). Функция R head позволяет вам просматривать первые n строк, а tail позволяет просматривать последние n строк

0 голосов
/ 01 января 2019

Также возможна tidyverse:

df %>%
 group_by(a) %>%
 top_n(2, row_number())

      a        b
  <dbl>    <dbl>
1    1.  343.   
2    1.   54.0  
3    2.   55.0  
4    2.   62.0  
5    3.   59.0  
6    3.   -9.00 
7    4.    0.   
8    4.   -0.500

Она берет верхние две строки с учетом номеров строк на группы.

0 голосов
/ 01 января 2019

Базовая опция R, использующая tapply, предназначена для поднабора последних двух строк для каждой группы.

df[unlist(tapply(1:nrow(df), df$a, tail, 2)), ]

#     a      b
#  <dbl>  <dbl>
#1     1  343  
#2     1   54  
#3     2   55  
#4     2   62  
#5     3   59  
#6     3   -9  
#7     4    0  
#8     4   -0.5

Или другая опция, использующая ave

df[as.logical(with(df, ave(1:nrow(df), a, FUN = function(x) x %in% tail(x, 2)))), ]
0 голосов
/ 01 января 2019

Поскольку это конкретный вопрос, основанный на dplyr

1 ) после group_by, используйте slice на row_number()

library(tidyverse)
df %>% 
   group_by(a) %>% 
   slice(tail(row_number(), 2))
# A tibble: 8 x 2
# Groups:   a [4]
#      a      b
#  <dbl>  <dbl>
#1     1  343  
#2     1   54  
#3     2   55  
#4     2   62  
#5     3   59  
#6     3   -9  
#7     4    0  
#8     4   -0.5

2 ) Или используйте filter из dplyr

df %>% 
   group_by(a) %>% 
   filter(row_number() >= (n() - 1))

3 ) или с do и tail

df %>%
    group_by(a) %>% 
    do(tail(., 2))

4 ) В дополнение к tidyverse, методы, мы также можем использовать компактные data.table

library(data.table)
setDT(df)[df[, .I[tail(seq_len(.N), 2)], a]$V1]

5 ) или by от base R

by(df, df$a, FUN = tail, 2)

6 ) или aggregate от base R

df[aggregate(c ~ a, transform(df, c = seq_len(nrow(df))), FUN = tail, 2)$c,]

7 ) или split с base R

do.call(rbind, lapply(split(df, df$a), tail, 2))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...