【问题标题】:Mutate a new column after grouping, summarizing, and evaluating for TRUE conditions在分组、汇总和评估 TRUE 条件后改变新列
【发布时间】:2020-10-13 02:53:49
【问题描述】:

我想在分组和评估行条件后创建下面的output 数据框。当我对数据框进行分组和汇总时,我可以看到福特的三个实例可以概括为:福特、1 辆 SUV 和 2 辆卡车。同理,Honda可以概括为Honda、2 Sedan,而Toyota可以概括为Toyota、1 Electric、1 Truck。此外,还需要汇总分组后的实例数。所以就福特来说,它出现了 3 次,本田出现了 2 次,丰田出现了 2 次。 我只对 Make 出现多次的情况感兴趣,因此 Kia 和 Nissan 在此集合中不相关,也不会显示在输出中。我计划在数据框列表上使用它的一种函数形式。这不是 100% 必要的,因为如果它没有以那种格式呈现,我可以将它放入一个函数中。

在:

structure(list(Set = c(1, 1, 1, 1, 1, 1, 1, 1, 1), Make = structure(c(1L, 
2L, 5L, 1L, 4L, 2L, 5L, 3L, 1L), .Label = c("Ford", "Honda", 
"Kia", "Nissan", "Toyota"), class = "factor"), Line = structure(c(5L, 
3L, 5L, 4L, 1L, 3L, 2L, 3L, 5L), .Label = c("CSUV", "Electric", 
"Sedan", "SUV", "Truck"), class = "factor")), class = "data.frame", row.names = c(NA, 
-9L))

>
  Set   Make     Line
1   1   Ford    Truck
2   1  Honda    Sedan
3   1 Toyota    Truck
4   1   Ford      SUV
5   1 Nissan     CSUV
6   1  Honda    Sedan
7   1 Toyota Electric
8   1    Kia    Sedan
9   1   Ford    Truck

in %>% dplyr::group_by(Set,Make,Line) %>% dplyr::summarise(n = n()) %>% dplyr::arrange(Make)

# A tibble: 7 x 4
# Groups:   Set, Make [5]
    Set Make   Line         n
  <dbl> <fct>  <fct>    <int>
1     1 Ford   SUV          1
2     1 Ford   Truck        2
3     1 Honda  Sedan        2
4     1 Kia    Sedan        1
5     1 Nissan CSUV         1
6     1 Toyota Electric     1
7     1 Toyota Truck        1

输出:

structure(list(Set = c(1, 1, 1), Groups = structure(1:3, .Label = c("Ford_1Suv_2Truck", 
"Honda_1Sedan_1Van", "Toyota_1Electric_1Truck"), class = "factor"), 
    TotalInstances = structure(c(2L, 1L, 1L), .Label = c("2", 
    "3"), class = "factor")), class = "data.frame", row.names = c(NA, 
-3L))

> 
  Set              Groups Cases
1   1    Ford_1Suv_2Truck     3
2   1        Honda_2Sedan     2
3   1 Toyota_1Electric_1Truck 2

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    使用summarisearrangeing 获得计数后,filter 基于计数列'n'的行或删除最后一组后的新计数,然后通过粘贴summarise (str_c ) 'n', 'Line' 列,获取'n' 的sum 来创建'Cases'

    library(dplyr)
    library(stringr)
    in %>% 
        dplyr::group_by(Set, Make, Line) %>%
        dplyr::arrange(Make) %>% 
        dplyr::summarise(Groups = str_c(n, Line, sep="", 
            collapse="_"), Cases = sum(n)) %>% 
        filter(n > 1) %>%        
        ungroup %>% 
        transmute(Set, Groups = str_c(Make, '_', Groups), Cases)
    

    -输出

    # A tibble: 3 x 3
    #    Set Groups                  Cases
    #  <dbl> <chr>                   <int>
    #1     1 Ford_1SUV_2Truck            3
    #2     1 Honda_2Sedan                2
    #3     1 Toyota_1Electric_1Truck     2
    

    我们可以通过 data.table 加快速度

    library(data.table)
    indt <- setDT(in)[, .(n = .N), .(Set, Make, Line)][order(Make)]
    indt1 <- indt[indt[, .I[.N > 1|n > 1], .(Set, Make)]$V1] 
    indt1[, .(Groups = paste0(n, Line, sep="", collapse="_"), Cases = sum(n)), .(Set, Make)][, Groups := str_c(Make, "_", Groups)]
    

    【讨论】:

    • 这是一个很好的解决方案,并且正是我想要的。但是,这在更大的数据集上非常缓慢。我的数据集大约有 30 万行,该操作从今天早上大约 8 点开始运行。你能想出什么方法来加速这个过程,要么消除任何不必要的操作,要么使用不同的库来分组、总结和变异?
    • @On_an_island 可能是 data.table 方法会更快。更新
    • 看来n() 中的filter(n() &gt; 1|n &gt; 1) 显着降低了您的代码速度。我运行了 8 个多小时,当我下班回家时,它仍然卡在过滤线上。所以我做了以下更改,它运行良好(快速):dplyr::arrange(Make) %&gt;% summarise(Groups = str_c(n, Line, sep="", collapse="_"), Cases = sum(n)) %&gt;% filter(n &gt; 1)。我接受您的回答,但我建议更改过滤器操作和顺序。
    • @On_an_island 谢谢。我用您的更改更新了帖子
    猜你喜欢
    • 1970-01-01
    • 2011-02-01
    • 1970-01-01
    • 2017-01-22
    • 1970-01-01
    • 1970-01-01
    • 2019-09-01
    • 2018-08-17
    • 1970-01-01
    相关资源
    最近更新 更多