【问题标题】:Group_by and summarise and preserve initial order without arrange RGroup_by 并汇总并保留初始顺序而不安排 R
【发布时间】:2021-05-14 05:06:36
【问题描述】:

我需要在group_bysummarise 之后保留行顺序。

这是初始数据集:


movmnt_id <- c("101", "101", "351", "601","601","351")
plant <- c("F5P", "F5D", "F5P", "F5D","F5D", "RUP")
loc <- c("CB00", "CB00", "CB00", "CB00","CB00","MOS1")
qty <- c(100, 100,100,10,90,88)
date <- c("2018-01-05","2018-01-05","2018-01-05","2018-01-11","2018-01-11","2018-01-22" )
time <- c("10:38:38","10:47:17", "10:47:09","17:20:31","17:20:24","12:00:54" )


df <-  data.frame(movmnt_id,  plant, loc, qty,date, time)
df

  movmnt_id  plant  loc   qty       date     time
1       101   F5P  CB00   100   2018-01-05   10:38:38
2       101   F5D  CB00   100   2018-01-05   10:47:17
3       351   F5P  CB00   100   2018-01-05   10:47:09
4       601   F5D  CB00    10   2018-01-11   17:20:31
5       601   F5D  CB00    90   2018-01-11   17:20:24
6       351   RUP  MOS1    88   2018-01-22   12:00:54

我需要先根据具体条件下单(这里的数据集和条件都大大简化了)。我是这样做的:

df2 <- df %>%
  
  dplyr::group_by( movmnt_id, plant, loc,date,time) %>%
  dplyr::summarise(total_qty = sum(qty)) %>%
  dplyr::arrange( date,time) %>%
  dplyr::ungroup()

df2

  movmnt_id plant loc   date       time     total_qty
  <fct>     <fct> <fct> <fct>      <fct>        <dbl>
1 101       F5P   CB00  2018-01-05 10:38:38       100
2 351       F5P   CB00  2018-01-05 10:47:09       100
3 101       F5D   CB00  2018-01-05 10:47:17       100
4 601       F5D   CB00  2018-01-11 17:20:24        90
5 601       F5D   CB00  2018-01-11 17:20:31        10
6 351       RUP   MOS1  2018-01-22 12:00:54        88

这个结果没问题。然后我需要按数量删除timestampsummarise
我的最后一次尝试是这样的:

df3  <- df2 %>%
  dplyr::group_by( movmnt_id, plant, loc,date) %>%
  dplyr::summarise(total_qty = sum(total_qty)) %>%
  dplyr::ungroup()

df3

  movmnt_id plant loc   date       total_qty
  <fct>     <fct> <fct> <fct>          <dbl>
1 101       F5D   CB00  2018-01-05       100
2 101       F5P   CB00  2018-01-05       100
3 351       F5P   CB00  2018-01-05       100
4 351       RUP   MOS1  2018-01-22        88
5 601       F5D   CB00  2018-01-11       100

这不行 - 我失去了之前的订单。

我需要的是movmnt_id = 601 的一行,并且与 df2 中的顺序相同,movmnt_id = 351 日期为 2018-01-05 应该在同一日期的动作 101 之间:

  movmnt_id plant loc   date       time     total_qty
  <fct>     <fct> <fct> <fct>      <fct>        <dbl>
1 101       F5P   CB00  2018-01-05 10:38:38       100
2 351       F5P   CB00  2018-01-05 10:47:09       100
3 101       F5D   CB00  2018-01-05 10:47:17       100
4 601       F5D   CB00  2018-01-11 17:20:24       100
5 351       RUP   MOS1  2018-01-22 12:00:54        88

基本上,如果分组条件中的所有值都相同,除了 qty - 这些行可以相加,但如果不是 - 必须保持顺序。

我该怎么做?

【问题讨论】:

  • 不,这还不够,它不适用于所有情况。重要的是先按时间戳排列。
  • 行排序与数据无关,除非您有时间序列。否则,聚合数据集将具有无保证的排序,并且仍将保持所需的属性。

标签: r dplyr group-by


【解决方案1】:

在这里,我按时间顺序为 id / plant / loc 组合创建了一个有序因子,这里称为“key”。然后当我们通过它聚合时(使用 count 代替 group_by %&gt;% summarize 的快捷方式),并且 count 使用它对输出进行排序。

library(forcats)  # alternatively, load with library(tidyverse)
df %>%
  arrange(date, time) %>%
  mutate(key = paste(movmnt_id, plant, loc) %>% as_factor %>% fct_inorder()) %>%
  count(key, date, movmnt_id, plant, loc, wt = qty, name = "total_qty")

           key       date movmnt_id plant  loc total_qty
1 101 F5P CB00 2018-01-05       101   F5P CB00       100
2 351 F5P CB00 2018-01-05       351   F5P CB00       100
3 101 F5D CB00 2018-01-05       101   F5D CB00       100
4 601 F5D CB00 2018-01-11       601   F5D CB00       100
5 351 RUP MOS1 2018-01-22       351   RUP MOS1        88

【讨论】:

    【解决方案2】:

    要保持来自df2 的相同顺序,您可以创建一个唯一键和match

    cols <- c('movmnt_id', 'plant', 'loc', 'date')
    df3 <- df3[order(match(do.call(paste, df3[cols]), do.call(paste, df2[cols]))), ]
    df3
    
    # movmnt_id plant loc   date       total_qty
    #  <chr>     <chr> <chr> <chr>          <dbl>
    #1 101       F5P   CB00  2018-01-05       100
    #2 351       F5P   CB00  2018-01-05       100
    #3 101       F5D   CB00  2018-01-05       100
    #4 601       F5D   CB00  2018-01-11       100
    #5 351       RUP   MOS1  2018-01-22        88
    

    【讨论】:

    • 这很好!谢谢!看起来也适用于更大的数据集。我可以请你解释一下它是如何工作的吗?我无法理解此代码如何影响行顺序。据我了解,它应该只影响列顺序。
    • 这是对行重新排序。将cols 中的值组合到df2 中,它会创建一个粘贴字符串,基于该字符串对df3 中的行进行重新排序。为了更好地理解这是如何工作的,我建议在较小的数据集上逐步运行。
    【解决方案3】:

    隐含地,您希望维护由 date 变量给出的顺序。在group_by 参数中首先列出date,以确保summarise 命令使用date 作为主键。

    df %>%
      group_by(date, movmnt_id, plant, loc) %>%
      summarise(total_qty = sum(qty)) %>%
      ungroup()
    #> `summarise()` has grouped output by 'date', 'movmnt_id', 'plant'. You can override using the `.groups` argument.
    #> # A tibble: 5 x 5
    #>   date       movmnt_id plant loc   total_qty
    #>   <chr>      <chr>     <chr> <chr>     <dbl>
    #> 1 2018-01-05 101       F5D   CB00        100
    #> 2 2018-01-05 101       F5P   CB00        100
    #> 3 2018-01-05 351       F5P   CB00        100
    #> 4 2018-01-11 601       F5D   CB00        100
    #> 5 2018-01-22 351       RUP   MOS1         88
    

    【讨论】:

    • 几乎,但是movmnt_id = 351date = 2018-01-05 的行改变了它的位置。它与运动 101 具有相同的日期,但根据交易历史必须在它们之间。这就是为什么我先按时间安排。数据集要复杂得多,在同一天可能会有很多不同数量的重复交易,所以首先要了解它们是否已经一一完成,然后数量可以在一行中求和还是有另一行。之间的交易 - 在这种情况下,它必须根据时间顺序进行拆分。
    猜你喜欢
    • 2016-12-29
    • 1970-01-01
    • 2022-01-12
    • 1970-01-01
    • 1970-01-01
    • 2015-07-13
    • 2021-11-14
    • 1970-01-01
    • 2021-11-16
    相关资源
    最近更新 更多