【问题标题】:How to select last N observation from each group in dplyr dataframe?如何从 dplyr 数据框中的每个组中选择最后 N 个观察值?
【发布时间】:2019-05-28 09:39:03
【问题描述】:

给定一个数据框:

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]]:下标超出范围

【问题讨论】:

标签: r dplyr


【解决方案1】:

试试tail().In R head函数可以让你预览前n行,而tail可以让你预览最后n行。

【讨论】:

    【解决方案2】:

    因为这是一个基于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) 或者使用filter from dplyr

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

    3) 或dotail

    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))
    

    【讨论】:

    • 为什么不用tail函数?
    • @steves 如果你使用df %&gt;% group_by(a) %&gt;% tail(2),它将获得整个数据集的最后两行,而不是在组内
    • 和 last() 函数?
    • @steves last 用于sumarise/mutate 内的不同上下文中,以获取特定列的last 元素。
    【解决方案3】:

    使用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)))), ]
    

    【讨论】:

      【解决方案4】:

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

      考虑到每组的行号,它占据了前两行。

      【讨论】:

      • 我需要最后 N 行。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-16
      • 1970-01-01
      • 2021-02-23
      • 2019-02-19
      • 1970-01-01
      相关资源
      最近更新 更多