【问题标题】:How to group and summarise by two variables如何按两个变量进行分组和汇总
【发布时间】:2017-12-21 16:49:23
【问题描述】:

我在多列上使用 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


    【解决方案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
    

    【讨论】:

    • 非常感谢。 Lyngbakr 有点早,所以我会给他打勾。
    • 请注意,Lyngbakr 的回答给出了 last 值,而不是最大值。
    【解决方案2】:

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

    输出

       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
    

    上面的 sn-p 使用“链接”(您可以认为它类似于%&gt;% 方法)来获得所需的输出。首先,我们得到AP 的累积总和并将其保存到total。在第二步中,我们按APtimestamp(到最近的分钟)分组,并获得新定义的变量total 的最大值。

    我发现data.table 有一种非常简洁的方法,非常适用于大型数据集。

    【讨论】:

      猜你喜欢
      • 2017-01-11
      • 2023-01-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多