【问题标题】:Efficiently concate character content within one column, by group in R在 R 中按组有效地连接一列中的字符内容
【发布时间】:2014-07-03 16:01:36
【问题描述】:

R 中对data.frame 执行类似连接操作的最快方法是什么?假设我有下表:

df <- data.frame(content = c("c1", "c2", "c3", "c4", "c5"),
                 groups = c("g1", "g1", "g1", "g2", "g2"),
                 stringsAsFactors = F)

df$groups <- as.factor(df$groups)

我想按组高效地连接content 列中单元格的内容,以接收相当于:

df2 <- data.frame(content = c("c1 c2 c3", "c4 c5"),
                  groups = c("g1", "g2"),
                  stringsAsFactors = F)

df2 $groups <- as.factor(df2 $groups)

我更喜欢一些dplyr 操作,但不知道如何应用它。

【问题讨论】:

    标签: r dataframe concatenation aggregate dplyr


    【解决方案1】:

    tapply 的近亲是 aggregate,它可以让你这样做:

    aggregate(content ~ groups, df, paste, collapse = " ")
    #   groups  content
    # 1     g1 c1 c2 c3
    # 2     g2    c4 c5
    

    因子被保留:

    str(.Last.value)
    # 'data.frame':  2 obs. of  2 variables:
    #  $ groups : Factor w/ 2 levels "g1","g2": 1 2
    #  $ content: chr  "c1 c2 c3" "c4 c5"
    

    既然你提到你正在寻找dplyr 方法,你可以尝试这样的事情:

    library(dplyr)
    df %>% group_by(groups) %>% summarise(content = paste(content, collapse = " "))
    # Source: local data frame [2 x 2]
    # 
    #   groups  content
    # 1     g1 c1 c2 c3
    # 2     g2    c4 c5
    

    【讨论】:

      【解决方案2】:

      使用data.table:

      library(data.table)
      dt = as.data.table(df)
      
      dt[, paste(content, collapse = " "), by = groups]
      #   groups       V1
      #1:     g1 c1 c2 c3
      #2:     g2    c4 c5
      

      由于 OP 中提到了速度,data.tabledplyr 相当接近(基本方法非常慢,没有必要测试它们):

      dt = data.table(content = sample(letters, 26e6, T), groups = LETTERS)
      df = as.data.frame(dt)
      
      system.time(dt[, paste(content, collapse = " "), by = groups])
      #   user  system elapsed 
      #   5.37    0.06    5.65 
      
      system.time(df %>% group_by(groups) %>% summarise(paste(content, collapse = " ")))
      #   user  system elapsed 
      #   7.10    0.13    7.67 
      

      【讨论】:

      • “基本方法超级慢,没有必要测试它们”。现在这只是卑鄙(但我不否认它的真实性!):-)
      【解决方案3】:

      这是使用base的tapply的方法

      splat<-with(df, tapply(content, groups, paste, collapse=" "))
      df2<-data.frame(groups=names(splat), content=splat, stringsAsFactors=F)
      df2$groups <- as.factor(df2$groups)
      

      给你

      #    groups  content
      # g1     g1 c1 c2 c3
      # g2     g2    c4 c5
      

      (额外的“g1/g2”是data.frame的行名)

      【讨论】:

      • 谢谢!非常感谢您的帮助,它为我节省了很多时间! =)
      猜你喜欢
      • 1970-01-01
      • 2021-02-01
      • 2022-11-19
      • 1970-01-01
      • 1970-01-01
      • 2010-12-18
      • 2018-08-21
      • 1970-01-01
      • 2019-06-17
      相关资源
      最近更新 更多