如何在dplyr Dataframe 中选择每组的最后N个观测值?

t1rydlwq  于 2023-03-10  发布在  其他
关注(0)|答案(5)|浏览(130)

给定 Dataframe :

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)

给我错误的结果。
我希望它是:

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

请告诉我这里出了什么问题?
我得到的错误是:
订单(order_by)n中出错:下标越界

wh6knrhe

wh6knrhe1#

因为这是基于dplyr的特定问题

1)在group_by之后,在row_number()上使用slice

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)或使用dplyr中的filter

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

3)或使用dotail

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

4)除了tidyverse方法外,我们还可以使用compact data.table

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

5)或base R中的by

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

6)或使用base R中的aggregate

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

7)或从base Rsplit

do.call(rbind, lapply(split(df, df$a), tail, 2))
3ks5zfa0

3ks5zfa02#

更新

dplyr 1.1.0将by参数引入到slice()系列动词中,以允许一次性分组操作:

library(dplyr)

df %>% 
  slice_tail(n = 2, by = a)

注:此时by是实验性的。
dplyr 1.0.0引入了slice_tail,使这变得简单:

library(dplyr)

df %>% 
  group_by(a) %>% 
  slice_tail(n = 2)

类似地,slice_head用于获取 * 前 * n行。

ds97pgxw

ds97pgxw3#

使用tapply的基本R选项是为每个组的最后两行设置子集。

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)))), ]
1szpjjfi

1szpjjfi4#

还有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

根据每组的行号,取前两行。

jk9hmnmh

jk9hmnmh5#

尝试tail()。在R中,head函数允许您预览前n行,而tail允许您预览后n行。

相关问题