将标记列表转换为 n 元语法

2023-12-07

我有一个已经标记化的文档列表:

dat <- list(c("texaco", "canada", "lowered", "contract", "price", "pay", 
"crude", "oil", "canadian", "cts", "barrel", "effective", "decrease", 
"brings", "companys", "posted", "price", "benchmark", "grade", 
"edmonton", "swann", "hills", "light", "sweet", "canadian", "dlrs", 
"bbl", "texaco", "canada", "changed", "crude", "oil", "postings", 
"feb", "reuter"), c("argentine", "crude", "oil", "production", 
"pct", "january", "mln", "barrels", "mln", "barrels", "january", 
"yacimientos", "petroliferos", "fiscales", "january", "natural", 
"gas", "output", "totalled", "billion", "cubic", "metrers", "pct", 
"billion", "cubic", "metres", "produced", "january", "yacimientos", 
"petroliferos", "fiscales", "added", "reuter"))

我正在尝试有效地将这个标记列表转换为 n 元语法列表。这是我到目前为止编写的函数:

find_ngrams <- function(x, n){

  if (n==1){ return(x)}

  out <- as.list(rep(NA, length(x)))

  for (i in 1:length(x)){
    words <- x[[i]]
    out[[i]] <- words

    for (j in 2:n){

      phrases <- sapply(1:j, function(k){
        words[k:(length(words)-n+k)]
      })

      phrases <- apply(phrases, 1, paste, collapse=" ")

      out[[i]]  <- c(out[[i]], phrases)

    }
  }
  return(out)
}

这对于查找 n 元语法来说效果很好,但似乎效率很低。将 for 循环替换为*apply函数仍然会让我陷入 3 层深度的循环:

result <- find_ngrams(dat, 2)
> result[[2]]
 [1] "argentine"                "crude"                    "oil"                     
 [4] "production"               "pct"                      "january"                 
 [7] "mln"                      "barrels"                  "mln"                     
[10] "barrels"                  "january"                  "yacimientos"             
[13] "petroliferos"             "fiscales"                 "january"                 
[16] "natural"                  "gas"                      "output"                  
[19] "totalled"                 "billion"                  "cubic"                   
[22] "metrers"                  "pct"                      "billion"                 
[25] "cubic"                    "metres"                   "produced"                
[28] "january"                  "yacimientos"              "petroliferos"            
[31] "fiscales"                 "added"                    "reuter"                  
[34] "argentine crude"          "crude oil"                "oil production"          
[37] "production pct"           "pct january"              "january mln"             
[40] "mln barrels"              "barrels mln"              "mln barrels"             
[43] "barrels january"          "january yacimientos"      "yacimientos petroliferos"
[46] "petroliferos fiscales"    "fiscales january"         "january natural"         
[49] "natural gas"              "gas output"               "output totalled"         
[52] "totalled billion"         "billion cubic"            "cubic metrers"           
[55] "metrers pct"              "pct billion"              "billion cubic"           
[58] "cubic metres"             "metres produced"          "produced january"        
[61] "january yacimientos"      "yacimientos petroliferos" "petroliferos fiscales"   
[64] "fiscales added"           "added reuter"            

该代码中是否有任何可以矢量化的重要部分?

/edit:这是 Matthew Plourde 函数的更新版本,它执行“up-to-n-grams”并且适用于整个列表:

find_ngrams_base <- function(x, n) {
  if (n == 1) return(x)
  out <- lapply(1:n, function(n_i) embed(x, n_i))
  out <- sapply(out, function(y) apply(y, 1, function(row) paste(rev(row), collapse=' ')))
  unlist(out)
}

find_ngrams_plourde <- function(x, ...){
  lapply(x, find_ngrams_base, ...)
}

我们可以对我编写的函数进行基准测试,发现它有点慢:

library(rbenchmark)
benchmark(
  replications=100,
  a <- find_ngrams(dat, 2),
  b <- find_ngrams(dat, 3),
  c <- find_ngrams(dat, 4),
  d <- find_ngrams(dat, 10),
  w <- find_ngrams_plourde(dat, 2),
  x <- find_ngrams_plourde(dat, 3),
  y <- find_ngrams_plourde(dat, 4),
  z <- find_ngrams_plourde(dat, 10),
  columns=c('test', 'elapsed', 'relative'),
  order='relative'
)
                               test elapsed relative
1          a <- find_ngrams(dat, 2)   0.040    1.000
2          b <- find_ngrams(dat, 3)   0.081    2.025
3          c <- find_ngrams(dat, 4)   0.117    2.925
5  w <- find_ngrams_plourde(dat, 2)   0.144    3.600
6  x <- find_ngrams_plourde(dat, 3)   0.212    5.300
7  y <- find_ngrams_plourde(dat, 4)   0.277    6.925
4         d <- find_ngrams(dat, 10)   0.361    9.025
8 z <- find_ngrams_plourde(dat, 10)   0.669   16.725

然而,它也发现了我的函数遗漏的很多 ngram(哎呀):

for (i in 1:length(dat)){
  print(setdiff(w[[i]], a[[i]]))
  print(setdiff(x[[i]], b[[i]]))
  print(setdiff(y[[i]], c[[i]]))
  print(setdiff(z[[i]], d[[i]]))
}

我觉得这两个函数都可以改进,但我想不出任何方法来避免三重循环(循环遍历向量,循环遍历所需的 ngram 数量,1-n,循环遍历单词以构造 ngram)

/编辑2: 这是根据马特的回答修改后的函数:

find_ngrams_2 <- function(x, n){
  if (n == 1) return(x)
  lapply(x, function(y) c(y, unlist(lapply(2:n, function(n_i) do.call(paste, unname(rev(data.frame(embed(y, n_i), stringsAsFactors=FALSE))))))))
}

它似乎返回了正确的 ngram 列表,并且(在大多数情况下)比我原来的函数更快:

library(rbenchmark)
benchmark(
  replications=100,
  a <- find_ngrams(dat, 2),
  b <- find_ngrams(dat, 3),
  c <- find_ngrams(dat, 4),
  d <- find_ngrams(dat, 10),
  w <- find_ngrams_2(dat, 2),
  x <- find_ngrams_2(dat, 3),
  y <- find_ngrams_2(dat, 4),
  z <- find_ngrams_2(dat, 10),
  columns=c('test', 'elapsed', 'relative'),
  order='relative'
)

                         test elapsed relative
5  w <- find_ngrams_2(dat, 2)   0.039    1.000
1    a <- find_ngrams(dat, 2)   0.041    1.051
6  x <- find_ngrams_2(dat, 3)   0.078    2.000
2    b <- find_ngrams(dat, 3)   0.081    2.077
7  y <- find_ngrams_2(dat, 4)   0.119    3.051
3    c <- find_ngrams(dat, 4)   0.123    3.154
4   d <- find_ngrams(dat, 10)   0.399   10.231
8 z <- find_ngrams_2(dat, 10)   0.436   11.179

这是一种方法embed.

find_ngrams <- function(x, n) {
    if (n == 1) return(x)
    c(x, apply(embed(x, n), 1, function(row) paste(rev(row), collapse=' ')))
}

您的功能似乎存在错误。如果你解决了这个问题,我们就可以做一个基准测试。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将标记列表转换为 n 元语法 的相关文章

  • 查找嵌套列表中元素的索引?

    我有一个类似的列表 mylist lt list a 1 b list A 1 B 2 c list C 1 D 3 是否有一种 无循环 方法来识别元素的位置 例如如果我想用 5 替换 C 的值 并且在哪里找到元素 C 并不重要 我可以这样
  • 在 Shiny 中设置一个绘图缩放以匹配另一个绘图缩放

    我正在尝试使用情节重排获取一个图的 x 轴缩放限制 并将它们应用到 Shiny 中的另一个图 到目前为止 我可以从 plot1 x轴限制 获取相关的plotly relayout数据 将其转换 从数字到日期 并在绘制 plot2 之前将其提
  • 有没有办法在 RStudio 中调试 RScript 调用?

    假设我从命令行运行 R 脚本 如下所示 Rscript prog R x y z 我想检查某一行的代码 目前 我无法在 RStudio 中以交互方式调试它 因为我不知道如何传递参数 由于它设计为从命令行运行 因此如何通过命令行 RStudi
  • 在 R 中进行 Cox 回归后,将预测危险比列添加到数据帧中

    在 R 中运行 Cox PH 回归后 我需要在数据框中添加预测风险比的列 数据框是面板数据 其中 numgvkey 如果公司标识符 和年龄是时间标识符 您可以从此链接下载一小部分日期 https drive google com file
  • 可以明确声明包依赖项的版本吗?

    我倾向于对我编写的代码进行明确而不是隐含的描述 因此 在成功创建自己的包之后 我立即想到的下一件事是如何最好地确保代码的健壮性和可靠性 其中一部分与我的包所依赖的包有关 实际问题 在这方面 是否可以明确声明需要 期望哪个版本的包依赖项 我正
  • 指定 R 中 hist() 中的 bin 数量?

    我尝试指定垃圾箱的数量hist R为10 如下 gt hist x breaks 10 但垃圾箱的数量并不完全是 10 我尝试了几个其他数量的垃圾箱 结果发生了同样的情况 hist says breaks可以指定 给出直方图单元格数量的单个
  • 如何调整ggplot直方图的时间刻度轴

    我正在使用一个数据框 其中一列包含POSIXct日期时间值 我正在尝试使用绘制这些时间戳的直方图ggplot2但我有两个问题 我不知道如何设置 binwidthgeom histogram 我想将每个垃圾箱设置为一天或一周 我尝试提供 di
  • 如何使用 r 中的 caret 包在最佳调整超参数的 10 倍交叉验证中获得每次折叠的预测?

    我试图使用 R 中的插入符包使用 10 倍交叉验证和 3 次重复来运行 SVM 模型 我想使用最佳调整的超参数获得每次折叠的预测结果 我正在使用以下代码 Load packages library mlbench library caret
  • 分离并重新附加“tools:rstudio”

    又名玩火 以下不起作用 rstd obj lt as environment tools rstudio detach tools rstudio attach rstd obj name tools rstudio 好吧 它似乎有效 但随
  • 使用 R 的 flextable 包时,有没有办法将传递给 add_header_lines() 的字符串部分加粗

    我正在使用我喜欢的 flextable 包为 Word 文档创建几个表格 但是 我在将表格标题中的部分文本加粗时遇到了一些麻烦 例如 我希望标题为 Table 1 我的表格标题的其余部分 而不是 表 1 我的表格标题的其余部分 I 找到这个
  • 在函数内部调用 clusterApply 时,性能会下降

    我遇到了一个奇怪的问题clusterApply 我已经能够尽可能地隔离它 如下所示 首先 我从全局环境运行以下代码 require parallel cl lt makeCluster rep localhost 20 SOCK xl lt
  • 将列表中的列转换为 R 中的数据框

    我有使用 R 创建的以下列表 set seed 326581 X1 rnorm 10 0 1 Y1 rnorm 10 0 2 data data frame X1 Y1 lst lt replicate 100 df smpl lt dat
  • 如何获得属于五分位数的x?

    我正在大学学习使用 R 进行计量经济学项目 所以请原谅我的笨拙 基本上 使用并给出 一个矩阵 股票价格 行 天 列 公司股票价格 另一个矩阵 市值 行 天 列 公司市值 我必须收集第三个矩阵每天观察的属于市值分布第一五分位数的股票价格 然后
  • R 更改小数位且不四舍五入

    gt signif 1 89 digits 2 1 1 9 我想要1 8 这有点笨拙 但它会起作用并保持所有数字 x lt 1 829380 trunc dec lt function x n floor x 10 n 10 n Resul
  • 逻辑回归/二项式的 glmnet 误差

    当尝试将 glmnet 与 family binomial 配合以进行逻辑回归拟合时 出现此错误 gt data lt read csv DAFMM HE16 matrix csv header F gt x lt as data fram
  • glmnet 未从 cv.glmnet 收敛 lambda.min

    我跑了20倍cv glmnet套索模型以获得 lambda 的 最佳 值 但是 当我尝试重现结果时glmnet 我收到一个错误 内容如下 Warning messages 1 from glmnet Fortran code error c
  • R:表格格式

    我有一个包含以下列的 Excel 文件 Column1 Column2 Column3 ab bb 0 5 ab bc 0 1 ab cd 0 7 ab dd 0 8 ac bb 0 2 ac bg 0 8 ac ee 0 8 ac dd
  • 使用outer代替expand.grid

    我正在寻找尽可能快的速度并留在基地做该做的事expand grid做 我用过outer为过去类似的目的创建一个向量 像这样的东西 v lt outer letters LETTERS paste0 unlist v lower tri v
  • R 中的 Websocket

    我设法在 R 中建立到 Mtgox websocket 的连接 规格如下 url https socketio mtgox com mtgox Currency USD https socketio mtgox com mtgox Curr
  • 单击 R 中的 Sankey Chart 线时添加额外的标签值

    以下 R 闪亮脚本创建一个桑基图 如下面的快照所示 我的要求是 当我单击左右节点之间的任何链接 即 a1 和 a2 时 我希望相应的 a3 的总和出现在标签中 例如 a1 中的 A 和 a2 中的 E 总共具有值 50 和 32 因此 我想

随机推荐