Applying group_by and summarise(sum) but keep columns with non-relevant conflicting data?

后端 未结 3 1579
生来不讨喜
生来不讨喜 2021-01-11 23:17

My question is very similar to Applying group_by and summarise on data while keeping all the columns' info but I would like to keep columns which get excluded because th

相关标签:
3条回答
  • 2021-01-11 23:54

    Here's a tidyverse solution that keeps your group_by statement the same. The key is to use mutate_if for each variable type first (i.e., numeric, character), then get distinct rows.


    library(tidyverse)
    #> Loading tidyverse: ggplot2
    #> Loading tidyverse: tibble
    #> Loading tidyverse: tidyr
    #> Loading tidyverse: readr
    #> Loading tidyverse: purrr
    #> Loading tidyverse: dplyr
    #> Conflicts with tidy packages ----------------------------------------------
    #> filter(): dplyr, stats
    #> lag():    dplyr, stats
    
    Label <- c("203c", "203c", "204a", "204a", "204a", "204a", "204a", "204a",
      "204a", "204a")
    Type <- c("wholefish", "flesh", "flesh", "fleshdelip", "formula", "formuladelip",
      "formula", "formuladelip", "wholefish", "wholefishdelip")
    Proportion <- c(1, 1, 0.67714, 0.67714, 0.32285, 0.32285, 0.32285, 0.32285,
      0.67714, 0.67714)
    N <- (1:10)
    C <- (1:10)
    Code <- c("c", "a", "a", "b", "a", "b", "c", "d", "c", "d")
    
    df <- data_frame(Label, Type, Proportion, N, C, Code)
    df
    #> # A tibble: 10 x 6
    #>    Label           Type Proportion     N     C  Code
    #>    <chr>          <chr>      <dbl> <int> <int> <chr>
    #>  1  203c      wholefish    1.00000     1     1     c
    #>  2  203c          flesh    1.00000     2     2     a
    #>  3  204a          flesh    0.67714     3     3     a
    #>  4  204a     fleshdelip    0.67714     4     4     b
    #>  5  204a        formula    0.32285     5     5     a
    #>  6  204a   formuladelip    0.32285     6     6     b
    #>  7  204a        formula    0.32285     7     7     c
    #>  8  204a   formuladelip    0.32285     8     8     d
    #>  9  204a      wholefish    0.67714     9     9     c
    #> 10  204a wholefishdelip    0.67714    10    10     d
    
    df %>%
      group_by(Label, Code) %>%
      mutate_if(is.numeric, sum) %>%
      mutate_if(is.character, funs(paste(unique(.), collapse = "_"))) %>%
      distinct()
    #> # A tibble: 6 x 6
    #> # Groups:   Label, Code [6]
    #>   Label                        Type Proportion     N     C  Code
    #>   <chr>                       <chr>      <dbl> <int> <int> <chr>
    #> 1  203c                   wholefish    1.00000     1     1     c
    #> 2  203c                       flesh    1.00000     2     2     a
    #> 3  204a               flesh_formula    0.99999     8     8     a
    #> 4  204a     fleshdelip_formuladelip    0.99999    10    10     b
    #> 5  204a           formula_wholefish    0.99999    16    16     c
    #> 6  204a formuladelip_wholefishdelip    0.99999    18    18     d
    
    0 讨论(0)
  • 2021-01-11 23:56

    Here are two other options:

    1) Nest columns into one column and then customize the summary by checking the data types:

    df %>% 
        group_by(Label, Code) %>% nest() %>% 
        mutate(data = map(data, 
            ~ as.tibble(map(.x, ~ if(is.numeric(.x)) sum(.x) else paste(.x, collapse="_")))
              )
        ) %>% unnest()
    
    # A tibble: 6 x 6
    #   Label   Code                        Type Proportion     N     C
    #  <fctr> <fctr>                       <chr>      <dbl> <int> <int>
    #1   203c      c                   wholefish    1.00000     1     1
    #2   203c      a                       flesh    1.00000     2     2
    #3   204a      a               flesh_formula    0.99999     8     8
    #4   204a      b     fleshdelip_formuladelip    0.99999    10    10
    #5   204a      c           formula_wholefish    0.99999    16    16
    #6   204a      d formuladelip_wholefishdelip    0.99999    18    18
    

    2) summarize separately and then join the result:

    numeric <- df %>% 
        group_by(Label, Code) %>% 
        summarise_if(is.numeric, sum)
    
    character <- df %>% 
        group_by(Label, Code) %>% 
        summarise_if(~ is.character(.) || is.factor(.), ~ paste(., collapse="_"))
    
    inner_join(numeric, character, by = c("Label", "Code"))
    # A tibble: 6 x 6
    # Groups:   Label [?]
    #   Label   Code Proportion     N     C                        Type
    #  <fctr> <fctr>      <dbl> <int> <int>                       <chr>
    #1   203c      a    1.00000     2     2                       flesh
    #2   203c      c    1.00000     1     1                   wholefish
    #3   204a      a    0.99999     8     8               flesh_formula
    #4   204a      b    0.99999    10    10     fleshdelip_formuladelip
    #5   204a      c    0.99999    16    16           formula_wholefish
    #6   204a      d    0.99999    18    18 formuladelip_wholefishdelip
    
    0 讨论(0)
  • 2021-01-12 00:05

    Here's the data.table solution, I'm assuming you want the mean() of Proportion, since these grouped proportions are likely not additive.

    setDT(df)
    
    df[, .(Type =paste(Type,collapse="_"), 
      Proportion=mean(Proportion),N= sum(N),C=sum(C)), by=.(Label,Code)]
      [order(Label)]
    
       Label Code                        Type Proportion  N  C
    1:  203c    c                   wholefish   1.000000  1  1
    2:  203c    a                       flesh   1.000000  2  2
    3:  204a    a               flesh_formula   0.499995  8  8
    4:  204a    b     fleshdelip_formuladelip   0.499995 10 10
    5:  204a    c           formula_wholefish   0.499995 16 16
    6:  204a    d formuladelip_wholefishdelip   0.499995 18 18
    

    I'm not sure this is the cleanest dplyr solution, but it works:

    df %>% group_by(Label, Code) %>% 
      mutate(Type = paste(Type,collapse="_")) %>% 
      group_by(Label,Type,Code) %>% 
      summarise(N=sum(N),C=sum(C),Proportion=mean(Proportion))
    

    Note the key here is to re-group once you create the combined Type column.

       Label                        Type   Code     N     C Proportion
      <fctr>                       <chr> <fctr> <int> <int>      <dbl>
    1   203c                       flesh      a     2     2   1.000000
    2   203c                   wholefish      c     1     1   1.000000
    3   204a               flesh_formula      a     8     8   0.499995
    4   204a     fleshdelip_formuladelip      b    10    10   0.499995
    5   204a           formula_wholefish      c    16    16   0.499995
    6   204a formuladelip_wholefishdelip      d    18    18   0.499995
    
    0 讨论(0)
提交回复
热议问题