【问题标题】:Aggregate numerical and character at once一次聚合数字和字符
【发布时间】:2020-10-15 15:57:05
【问题描述】:

我需要一次聚合不同类的多个变量。

test<- data.frame (name = c("anna", "joe", "anna"), 
                   party = c("red", "blue", "red"),
                   text = c("hey there", "we ate an apple", "i took a walk"), 
                   numberofwords = c(2, 4, 4), 
                   score1 = 1:3, 
                   score2 = 4:6)

现在是这个样子

#   name    party      text           numberofwords score1 score2
#1  anna    red       hey there             2         1      4
#2  joe     blue    we ate an apple         4         2      5
#3  anna    red      i took a walk          4         3      6

我想根据姓名和派对聚合 score1、score2、numberofwords、文本变量。

想要的结果是:

#   name  party            text                  numberofwords score1 score2
#1  anna  red           hey there i took a walk       6           4      10
#2   joe  blue           we ate an apple              4           2      5

【问题讨论】:

    标签: r dataframe dplyr tidyverse


    【解决方案1】:

    使用最新版本的dplyracross

    test %>%
      group_by(name, party) %>%
      summarize(
        across(text, paste, collapse = " "),
        across(where(is.numeric), sum)
      )
    # # A tibble: 2 x 6
    #   name  party text                    numberofwords score1 score2
    #   <chr> <chr> <chr>                           <dbl>  <int>  <int>
    # 1 anna  red   hey there i took a walk             6      4     10
    # 2 joe   blue  we ate an apple                     4      2      5   
    

    旧版本,保持第一party值:

    test %>%
      group_by(name) %>%
      summarize(
        across(party, first),
        across(text, paste, collapse = " "),
        across(where(is.numeric), sum)
      )
    # # A tibble: 2 x 6
    #   name  party text                    numberofwords score1 score2
    #   <chr> <chr> <chr>                           <dbl>  <int>  <int>
    # 1 anna  red   hey there i took a walk             6      4     10
    # 2 joe   blue  we ate an apple                     4      2      5   
    

    【讨论】:

    • 好,我还没习惯across。这比使用if else 更好。
    • 一开始我总是被绊倒,因为我想使用summarize(across(..cols..), fun),不明白为什么这个函数是inside。然后我意识到你可以在同一个summarize 中做多个acrosses,一切都点击了,我喜欢它。
    【解决方案2】:

    我们可以根据dplyr中每一列的类做一个条件summarise

    library(dplyr)
    
    test %>% 
      mutate_at("text", as.character) %>% 
      group_by(name) %>% 
      summarise_all(list(~if(is.numeric(.)) sum(., na.rm = TRUE)  
                          else if(is.factor(.)) first(.) 
                          else paste(., collapse = " ")))
    
    #> # A tibble: 2 x 6
    #>   name  party text                    numberofwords score1 score2
    #>   <fct> <fct> <chr>                           <dbl>  <int>  <int>
    #> 1 anna  red   hey there i took a walk             6      4     10
    #> 2 joe   blue  we ate an apple                     4      2      5
    

    【讨论】:

      【解决方案3】:

      base R 中,我们可以使用aggregatemerge 来做到这一点

      out1 <- aggregate(cbind(numberofwords, score1, score2) ~ name + party, test, sum)
      out2 <- aggregate(text ~ name + party, test, paste, collapse=' ')
      merge(out1, out2)
      

      -输出

      # name party numberofwords score1 score2                    text
      #1 anna   red             6      4     10 hey there i took a walk
      #2  joe  blue             4      2      5         we ate an apple
      

      【讨论】:

        【解决方案4】:

        尝试这种方法,首先聚合文本变量,然后聚合连续变量。之后合并所有。这里使用dplyr的代码:

        library(dplyr)
        #Data
        test<- data.frame (name = c("anna", "joe", "anna"), 
                           party =c("red", "blue", "red"),
                           text = c("hey there", "we ate an apple", "i took a walk"),
                           numberofwords = c(2,4,4),
                           score1 = 1:3, score2= 4:6,stringsAsFactors = F)
        #First aggregate text after that aggregate continuous variables and merge
        new <- test %>% 
          group_by(name,party) %>% summarise(text=paste0(text,collapse = ' ')) %>%
          left_join(
            test %>% select(-text) %>%
              group_by(name,party) %>%
              summarise_all(sum,na.rm=T)
          )
        

        输出:

        # A tibble: 2 x 6
        # Groups:   name [2]
          name  party text                    numberofwords score1 score2
          <chr> <chr> <chr>                           <dbl>  <int>  <int>
        1 anna  red   hey there i took a walk             6      4     10
        2 joe   blue  we ate an apple                     4      2      5
        

        【讨论】:

          猜你喜欢
          • 2016-08-02
          • 2015-02-14
          • 1970-01-01
          • 1970-01-01
          • 2023-04-04
          • 2020-12-17
          • 2017-09-14
          • 2020-07-21
          • 1970-01-01
          相关资源
          最近更新 更多