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

问题描述 投票:0回答:2

我在多列上使用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. 每分钟聚合运行总计的最大值。

换句话说,我想要这个输出:

            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部分。也就是说,我想知道如何执行聚合,以便后一个数据帧中的第二行被压缩以提供所需的输出。

r dplyr
2个回答
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
投票

这是一个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")

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

OUTPUT

   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

上面的代码片段使用“链接”(你可以认为它类似于%>%方法)来获得所需的输出。首先,我们通过AP获得累积金额并将其保存到total。在第二步中,我们按APtimestamp分组(到最近的分钟)并获得新定义的变量total的最大值。

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

© www.soinside.com 2019 - 2024. All rights reserved.