【问题标题】:String decomposition字符串分解
【发布时间】:2016-02-05 13:16:09
【问题描述】:

我需要使用 R 分解大约 7500 万个字符串。我需要做一些事情,比如创建一个术语文档矩阵,其中文档中出现的每个单词都成为矩阵中的一列,并且在任何出现术语的地方,矩阵元素编码为 1。

我有: 大约 7500 万个字符串,长度从大约 0-100 个字符不等;它们代表一个时间序列,提供有关该时期发生的事情的编码信息。每个代码都是一个字符,对应一个时间段。

我需要: 某种矩阵或传达信息的方式会带走时间序列,并告诉我每个序列中某个代码被报告了多少次。

例如: 字符串“ABCDEFG-123”将成为矩阵中的一行,其中每个字符将被记录为出现一次。如果这太难了,0 和 1 的矩阵也会给我一些信息,但我希望尽可能多地保留信息。

有没有人知道如何快速做到这一点?有 20 种可能的代码。

【问题讨论】:

    标签: r string performance matrix character


    【解决方案1】:

    例子:

    my20chars = c(LETTERS[1:10], 0:9)
    
    set.seed(1)
    x = replicate(1e4, paste0(sample(c(my20chars,"-"),10, replace=TRUE), collapse=""))
    

    一种方法:

    library(data.table)
    
    d = setDT(stack(strsplit(setNames(x,x),"")))
    dcast(d[ values %in% my20chars ], ind ~ values, fun = length)
    

    结果:

                  ind 0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J
        1: ---8EEAD8I 0 0 0 0 0 0 0 0 2 0 1 0 0 1 2 0 0 0 1 0
        2: --33B6E-32 0 0 1 3 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 0
        3: --3IFBG8GI 0 0 0 1 0 0 0 0 1 0 0 1 0 0 0 1 2 0 2 0
        4: --4210I8H5 1 1 1 0 1 1 0 0 1 0 0 0 0 0 0 0 0 1 1 0
        5: --5H4DE9F- 0 0 0 0 1 1 0 0 0 1 0 0 0 1 1 1 0 1 0 0
       ---                                                   
     9996: JJFJBJ24AJ 0 0 1 0 1 0 0 0 0 0 1 1 0 0 0 1 0 0 0 5
     9997: JJI-J-0FGB 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 1 0 1 3
     9998: JJJ1B54H63 0 1 0 1 1 1 1 0 0 0 0 1 0 0 0 0 0 1 0 3
     9999: JJJED7A3FI 0 0 0 1 0 0 0 1 0 0 1 0 0 1 1 1 0 0 1 3
    10000: JJJIF6GI13 0 1 0 1 0 0 1 0 0 0 0 0 0 0 0 1 1 0 2 3
    

    基准测试:

    library(microbenchmark)
    
    nstrs  = 1e5
    nchars = 10
    x = replicate(nstrs, paste0(sample(c(my20chars,"-"), nchars, replace=TRUE), collapse=""))
    
    microbenchmark(
    dcast = {
      d = setDT(stack(strsplit(setNames(x,x),"")))
      dcast(d[ values %in% my20chars ], ind ~ values, fun = length, value.var="ind")
    },
    times = 10)
    
    # Unit: seconds
    #   expr      min       lq     mean   median       uq      max neval
    #  dcast 3.112633 3.423935 3.480692 3.494176 3.573967 3.741931    10
    

    因此,这不足以处理 OP 的 7500 万个字符串,但可能是一个不错的起点。

    【讨论】:

    • 刚刚注意到,如果字符串出现多次,它们会在结果中合并。例如,如果您将nchars 降为喜欢3,您会看到这一点。不确定是否需要。
    【解决方案2】:

    我真的很喜欢@Frank 的解决方案,但这是另一种方式,它有两个优点:

    • 它使用稀疏矩阵格式,因此您更有可能将所有内容都放入内存;和

    • 它(甚至)更简单。

    它使用我们的 quanteda 包,您可以在其中标记每个字符串中的字符,并在一个命令中从这些字符中形成一个 文档特征矩阵

    my20chars = c(LETTERS[1:10], 0:9)
    set.seed(1)
    x = replicate(1e4, paste0(sample(c(my20chars,"-"),10, replace=TRUE), collapse=""))
    
    require(quanteda)
    myDfm <- dfm(x, what = "character", toLower = FALSE, verbose = FALSE)
    # for equivalent printing, does not change content:
    myDfm <- myDfm[, order(features(myDfm))]
    rownames(myDfm) <- x
    head(myDfm)
    # Document-feature matrix of: 6 documents, 20 features.
    # 6 x 20 sparse Matrix of class "dfmSparse"
    #             features
    # docs         0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J
    #   FH29E8933B 0 0 1 2 0 0 0 0 1 2 0 1 0 0 1 1 0 1 0 0
    #   ED4I605-H6 1 0 0 0 1 1 2 0 0 0 0 0 0 1 1 0 0 1 1 0
    #   9E3CFIAI8H 0 0 0 1 0 0 0 0 1 1 1 0 1 0 1 1 0 1 2 0
    #   020D746C5I 2 0 1 0 1 1 1 1 0 0 0 0 1 1 0 0 0 0 1 0
    #   736116A054 1 2 0 1 1 1 2 1 0 0 1 0 0 0 0 0 0 0 0 0
    #   08JFBCG03I 2 0 0 1 0 0 0 0 1 0 0 1 1 0 0 1 1 0 1 1
    

    缺点:

    • 它(慢得多)。

    基准测试:

    microbenchmark(
        dcast = {
            d = setDT(stack(strsplit(setNames(x,x),"")))
            dcast(d[ values %in% my20chars ], ind ~ values, fun = length, value.var="ind")
        },
        quanteda = dfm(x, what = "character", toLower = FALSE, removePunct = FALSE, verbose = FALSE),
        times = 10)
    # Unit: seconds
    #      expr       min        lq      mean    median        uq       max naval
    #     dcast  2.380971  2.423677  2.465338  2.429331  2.521256  2.636102    10
    #  quanteda 21.106883 21.168145 21.369443 21.345173 21.519018 21.883966    10
    

    【讨论】:

      猜你喜欢
      • 2021-11-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多