如何通过两个变量进行分组和汇总

时间:2017-12-21 16:49:23

标签: r dplyr

我在多列上使用group_by()时遇到问题。示例数据集如下:

dput(test)
structure(list(timestamp = structure(c(1506676980, 1506676980, 
1506676980, 1506677040, 1506677280, 1506677340, 1506677460), class = c("POSIXct", 
"POSIXt"), tzone = "UTC"), plusminus = c(-1, 1, 1, 1, 1, 1, -1
), AP = structure(c(1L, 2L, 2L, 2L, 2L, 1L, 2L), .Label = c("A", 
"B"), class = "factor")), .Names = c("timestamp", "plusminus", 
"AP"), row.names = c(NA, -7L), class = "data.frame")

看起来如下:

            timestamp plusminus AP
1 2017-09-29 09:23:00        -1  A
2 2017-09-29 09:23:00         1  B
3 2017-09-29 09:23:00         1  B
4 2017-09-29 09:24:00         1  B
5 2017-09-29 09:28:00         1  B
6 2017-09-29 09:29:00         1  A
7 2017-09-29 09:31:00        -1  B

我想做以下事情:

  1. 计算“AP'”中每个级别的运行总计变量
  2. 每分钟聚合运行总计的最大值。
  3. 换句话说,我想要这个输出:

                timestamp total AP
    1 2017-09-29 09:23:00    -1  A
    2 2017-09-29 09:23:00     2  B
    3 2017-09-29 09:24:00     3  B
    4 2017-09-29 09:28:00     4  B
    5 2017-09-29 09:29:00     0  A
    6 2017-09-29 09:31:00     3  B
    

    通过以下方式轻松完成第1部分:

    test %>% group_by(AP) %>% mutate(total = cumsum(plusminus))
    

    给出:

    # A tibble: 7 x 4
    # Groups:   AP [2]
                timestamp plusminus     AP total
                   <dttm>     <dbl> <fctr> <dbl>
    1 2017-09-29 09:23:00        -1      A    -1
    2 2017-09-29 09:23:00         1      B     1
    3 2017-09-29 09:23:00         1      B     2
    4 2017-09-29 09:24:00         1      B     3
    5 2017-09-29 09:28:00         1      B     4
    6 2017-09-29 09:29:00         1      A     0
    7 2017-09-29 09:31:00        -1      B     3
    

    但是我不知道如何做第2部分。也就是说,我想知道如何执行聚合,以便后一个数据帧中的第二行被压缩以提供所需的输出。

2 个答案:

答案 0 :(得分:1)

计算运行总计后,需要重新分组以将每个时间戳-AP对组合在一起,然后汇总以保持最大值。如果你想保留最后一个值(而不是最大值),你可以保留最后一行(你也可以使用slice(n()))。在这里,答案是相同的,但请确保您的数据是这样的。

test %>%
  group_by(AP) %>%
  mutate(total = cumsum(plusminus)) %>%
  group_by(timestamp, AP) %>%
  summarise(maxTotal = max(total)
            , lastTotal = total[n()])

给出

            timestamp     AP maxTotal lastTotal
               <dttm> <fctr>    <dbl>     <dbl>
1 2017-09-29 09:23:00      A       -1        -1
2 2017-09-29 09:23:00      B        2         2
3 2017-09-29 09:24:00      B        3         3
4 2017-09-29 09:28:00      B        4         4
5 2017-09-29 09:29:00      A        0         0
6 2017-09-29 09:31:00      B        3         3

答案 1 :(得分:1)

以下是data.table方法:

数据

p <- structure(list(timestamp = structure(c(1506676980, 1506676980, 
1506676980, 1506677040, 1506677280, 1506677340, 1506677460), class = c("POSIXct", 
"POSIXt"), tzone = "UTC"), plusminus = c(-1, 1, 1, 1, 1, 1, -1
), AP = structure(c(1L, 2L, 2L, 2L, 2L, 1L, 2L), .Label = c("A", 
"B"), class = "factor")), .Names = c("timestamp", "plusminus", 
"AP"), row.names = c(NA, -7L), class = "data.frame")

<强> CODE

library(data.table)
p <- as.data.table(p)
p[, total:= cumsum(plusminus), by = AP][, max(total), by = .(AP, lubridate::round_date(timestamp, unit = "min"))]

<强>输出

   AP           lubridate V1
1:  A 2017-09-29 09:23:00 -1
2:  B 2017-09-29 09:23:00  2
3:  B 2017-09-29 09:24:00  3
4:  B 2017-09-29 09:28:00  4
5:  A 2017-09-29 09:29:00  0
6:  B 2017-09-29 09:31:00  3

以上代码段使用&#34; chaining&#34; (您可以认为它类似于%>%方法)以获得所需的输出。首先,我们得到AP的累计和,并将其保存到total。在第二步中,我们按APtimestamp分组(到最近的分钟)并获取新定义的变量total的最大值。

我发现data.table有一个非常干净的方法,适用于大型数据集。