在一段时间内按组查找平均值并检索同一时期的最后日期

时间:2017-08-21 16:37:38

标签: r dataframe dplyr data.table

下面是一个可重现的数据表,其中包含四列:

  1. 日期
  2. 类别
  3. 值1
  4. value2
  5. 正如标题所示,我想计算每个类别的 value1 value2 的平均值,并在结果数据框中保留这些类别的最后观察日期

    以下是输入:

    # Libraries
    library(dplyr)
    library(data.table)
    
    # Reproducible data table
    set.seed(1234)
    date <- seq(as.Date("2017-01-01"), by = "month", length.out = 10)
    category <- (c('A','A','B','B','C','C','C','C','C', 'C'))
    value1 <- sample(seq(from = 91, to = 100, by = 1))
    value2 <- sample(seq(from = 51, to = 60, by = 1))
    dt <- data.table(date, category, value1, value2)
    print(dt)
    
              date category value1 value2
     1: 2017-01-01        A     92     57
     2: 2017-02-01        A     96     55
     3: 2017-03-01        B     95     53
     4: 2017-04-01        B     98     60
     5: 2017-05-01        C     99     52
     6: 2017-06-01        C     94     59
     7: 2017-07-01        C     91     56
     8: 2017-08-01        C     97     51
     9: 2017-09-01        C    100     58
    10: 2017-10-01        C     93     54
    

    以下是我目前的情况:

    dt2 <- dt %>% group_by(category) %>% summarise_each(funs(mean))
    print(dt2)
    
    # A tibble: 3 x 4
      category       date   value1 value2
         <chr>     <date>    <dbl>  <dbl>
    1        A 2017-01-16 94.00000   56.0
    2        B 2017-03-16 96.50000   56.5
    3        C 2017-07-16 95.66667   55.0
    

    以下是所需的输出:

      category       date   value1 value2
    1        A 2017-02-01 94.00000   56.0
    2        B 2017-04-01 96.50000   56.5
    3        C 2017-10-01 95.66667   55.0
    

    感谢您的任何建议!

2 个答案:

答案 0 :(得分:6)

以下是data.table方法。我们可以使用.()参数在j中执行计算,并在by参数中设置分组。

dt[, .(date = last(date), value1 = mean(value1), value2 = mean(value2)), by = category]

这是弗兰克开发的一种更有效的方式,作为对这篇文章的评论。这种方法只需要编写一次mean函数,使用.SD.SDcols来指定要汇总的列。

dt[, c(.(date = last(date)), lapply(.SD, mean)), by = category, .SDcols = value1:value2]

如果你想使用dplyr,你可以使用Z.Lin的方法。但是,如果有很多值列,例如value1value10,您可以执行以下操作。

dt %>%
  group_by(category) %>%
  summarise_all(funs(if_else(is.numeric(.), mean(.), last(.))))

如果列是数字,此代码将仅计算平均值,否则,它将报告组的最后一行。

最后提醒一下,summarise_each已被弃用。请使用summarise_allsummarise_ifsummarise_at

答案 1 :(得分:3)

这是你要找的吗?

dt %>%
  group_by(category) %>%
  summarise(date = max(date),
            value1 = mean(value1),
            value2 = mean(value2)) %>%
  ungroup()

# A tibble: 3 x 4
  category       date   value1 value2
     <chr>     <date>    <dbl>  <dbl>
1        A 2017-02-01 94.00000   56.0
2        B 2017-04-01 96.50000   56.5
3        C 2017-10-01 95.66667   55.0