【问题标题】:R: Aggregate character strings with cR:用 c 聚合字符串
【发布时间】:2014-01-30 07:14:16
【问题描述】:

我有一个包含两列的数据框:一列是字符串,另一列是整数。

> rnames = sapply(1:20, FUN=function(x) paste("item", x, sep="."))
> x <- sample(c(1:5), 20, replace = TRUE)
> df <- data.frame(x, rnames)
> df
   x  rnames
1  5  item.1
2  3  item.2
3  5  item.3
4  3  item.4
5  1  item.5
6  3  item.6
7  4  item.7
8  5  item.8
9  4  item.9
10 5 item.10
11 5 item.11
12 2 item.12
13 2 item.13
14 1 item.14
15 3 item.15
16 4 item.16
17 5 item.17
18 4 item.18
19 1 item.19
20 1 item.20

我正在尝试使用 'c' 或 'list' 函数将字符串聚合到字符串(字符)的列表或向量中,但得到了奇怪的结果:

> aggregate(rnames ~ x, df, c)
  x             rnames
1 1      16, 6, 11, 13
2 2               4, 5
3 3      12, 15, 17, 7
4 4      18, 20, 8, 10
5 5 1, 14, 19, 2, 3, 9

当我使用 'paste' 而不是 'c' 时,我可以看到聚合工作正常 - 但结果不是我想要的。

> aggregate(rnames ~ x, df, paste)
  x                                            rnames
1 1                 item.5, item.14, item.19, item.20
2 2                                  item.12, item.13
3 3                   item.2, item.4, item.6, item.15
4 4                  item.7, item.9, item.16, item.18
5 5 item.1, item.3, item.8, item.10, item.11, item.17

我正在寻找的是每个聚合组都将呈现为一个向量或一个 lit(因此使用 c),而不是我通过“粘贴”得到的单个字符串。类似于以下内容(实际上不起作用):

> aggregate(rnames ~ x, df, c)
  x                                            rnames
1 1                 item.5, item.14, item.19, item.20
2 2                                  item.12, item.13
3 3                   item.2, item.4, item.6, item.15
4 4                  item.7, item.9, item.16, item.18
5 5 item.1, item.3, item.8, item.10, item.11, item.17

任何帮助将不胜感激。

【问题讨论】:

    标签: r aggregate


    【解决方案1】:

    你掉进了data.frame的惯用陷阱:你的字符栏不是字符栏,是因素栏!因此结果中的数字而不是字符:

    > rnames = sapply(1:20, FUN=function(x) paste("item", x, sep="."))
    > x <- sample(c(1:5), 20, replace = TRUE)
    > df <- data.frame(x, rnames)
    > str(df)
    'data.frame':   20 obs. of  2 variables:
     $ x     : int  2 5 5 5 5 4 3 3 2 4 ...
     $ rnames: Factor w/ 20 levels "item.1","item.10",..: 1 12 14 15 16 17 18 19 20 2 ...
    

    为防止转换为因子,请在对 data.frame 的调用中使用参数 stringAsFactors=FALSE

    > df <- data.frame(x, rnames,stringsAsFactors=FALSE)
    > str(df)
    'data.frame':   20 obs. of  2 variables:
     $ x     : int  5 5 3 5 5 3 2 5 1 5 ...
     $ rnames: chr  "item.1" "item.2" "item.3" "item.4" ...
    > aggregate(rnames ~ x, df, c)
      x                                                                              rnames
    1 1                                                            item.9, item.13, item.17
    2 2                                                                              item.7
    3 3                                                             item.3, item.6, item.19
    4 4                                                           item.12, item.15, item.16
    5 5 item.1, item.2, item.4, item.5, item.8, item.10, item.11, item.14, item.18, item.20
    

    避免转换为因子的另一种解决方案是函数I

    > df <- data.frame(x, I(rnames))
    > str(df)
    'data.frame':   20 obs. of  2 variables:
     $ x     : int  3 5 4 5 4 5 3 3 1 1 ...
     $ rnames:Class 'AsIs'  chr [1:20] "item.1" "item.2" "item.3" "item.4" ...
    

    摘自?I

    在函数 data.frame 中。通过将对象包含在 I() 中来保护对象 对 data.frame 的调用禁止将字符向量转换为 因素和名称的删除,并确保矩阵 作为单列插入。我也可以用来保护物体 要添加到数据框,或转换为数据框 通过 as.data.frame。

    它通过将类“AsIs”添加到对象的 类。 “AsIs”类有一些自己的方法,包括 for [, as.data.frame,打印和格式化。

    【讨论】:

      【解决方案2】:

      不确定您正在寻找的究竟是什么......所以也许一些参考输出可以让我们了解我们的目标是什么?

      但是,由于您的最后一段代码似乎接近您所追求的,也许像以下这样的解决方案会起作用:

      > library(plyr)
      > ddply(df, .(x), summarize, rnames = paste(rnames, collapse = "|"))
        x                                         rnames
      1 1                         item.9|item.11|item.20
      2 2                  item.1|item.2|item.15|item.16
      3 3                                  item.7|item.8
      4 4           item.4|item.5|item.6|item.12|item.13
      5 5 item.3|item.10|item.14|item.17|item.18|item.19
      

      您可以通过将折叠参数更改为 paste() 来改变单个元素的粘贴方式。

      或者,如果您只想让每个组作为投票人,那么您可以使用以下方法:

      > df$rnames = as.character(df$rnames)
      > L = dlply(df, .(x), function(df) {df$rnames})
      > L
      $`1`
      [1] "item.9"  "item.11" "item.20"
      
      $`2`
      [1] "item.1"  "item.2"  "item.15" "item.16"
      
      $`3`
      [1] "item.7" "item.8"
      
      $`4`
      [1] "item.4"  "item.5"  "item.6"  "item.12" "item.13"
      
      $`5`
      [1] "item.3"  "item.10" "item.14" "item.17" "item.18" "item.19"
      
      attr(,"split_type")
      [1] "data.frame"
      attr(,"split_labels")
        x
      1 1
      2 2
      3 3
      4 4
      5 5
      

      这会给你一个向量列表,这就是你所追求的。并且每个组都可以从结果列表中索引出来:

      > L[[1]]
      [1] "item.9"  "item.11" "item.20"
      

      【讨论】:

      • 我编辑了这个问题。我想要得到的是每个聚合组都将作为向量/列表返回,而不是我用“粘贴”得到的单个字符串。
      猜你喜欢
      • 1970-01-01
      • 2015-02-02
      • 2020-12-17
      • 1970-01-01
      • 1970-01-01
      • 2013-07-04
      • 2014-09-02
      • 2017-09-14
      • 1970-01-01
      相关资源
      最近更新 更多