向量化 for 循环以加速 R 中的程序

2024-01-05

我正在寻找一些简单的矢量化方法for loop在 R 中。 我有以下数据框,其中包含句子和两本正面和负面单词的字典:

# Create data.frame with sentences
sent <- data.frame(words = c("just right size and i love this notebook", "benefits great laptop",
                         "wouldnt bad notebook", "very good quality", "orgtop",
                         "great improvement for that bad product but overall is not good", "notebook is not good but i love batterytop"), user = c(1,2,3,4,5,6,7),
               stringsAsFactors=F)

# Create pos/negWords
posWords <- c("great","improvement","love","great improvement","very good","good","right","very","benefits",
          "extra","benefit","top","extraordinarily","extraordinary","super","benefits super","good","benefits great",
          "wouldnt bad")
negWords <- c("hate","bad","not good","horrible")

现在,我创建原始数据框的副本来模拟大数据集:

# Replicate original data.frame - big data simulation (700.000 rows of sentences)
df.expanded <- as.data.frame(replicate(100000,sent$words))
# library(zoo)
sent <- coredata(sent)[rep(seq(nrow(sent)),100000),]
rownames(sent) <- NULL

对于下一步,我必须对字典中的单词及其情绪分数进行降序排序(正字 = 1 和负字 = -1)。

# Ordering words in pos/negWords
wordsDF <- data.frame(words = posWords, value = 1,stringsAsFactors=F)
wordsDF <- rbind(wordsDF,data.frame(words = negWords, value = -1))
wordsDF$lengths <- unlist(lapply(wordsDF$words, nchar))
wordsDF <- wordsDF[order(-wordsDF[,3]),]
rownames(wordsDF) <- NULL

然后我用 for 循环定义以下函数:

# Sentiment score function
scoreSentence2 <- function(sentence){
  score <- 0
  for(x in 1:nrow(wordsDF)){
    matchWords <- paste("\\<",wordsDF[x,1],'\\>', sep="") # matching exact words
    count <- length(grep(matchWords,sentence)) # count them
    if(count){
      score <- score + (count * wordsDF[x,2]) # compute score (count * sentValue)
      sentence <- gsub(paste0('\\s*\\b', wordsDF[x,1], '\\b\\s*', collapse='|'), ' ', sentence) # remove matched words from wordsDF
      # library(qdapRegex)
      sentence <- rm_white(sentence)
    }
  }
  score
}

我在数据框中的句子上调用前面的函数:

# Apply scoreSentence function to sentences
SentimentScore2 <- unlist(lapply(sent$words, scoreSentence2))
# Time consumption for 700.000 sentences in sent data.frame:
# user       system    elapsed
# 1054.19    0.09      1056.17
# Add sentiment score to origin sent data.frame
sent <- cbind(sent, SentimentScore2)

期望的输出是:

Words                                             user      SentimentScore2
just right size and i love this notebook          1         2
benefits great laptop                             2         1
wouldnt bad notebook                              3         1
very good quality                                 4         1
orgtop                                            5         0
  .
  .
  .

等等...

请任何人都可以帮助我减少我原来方法的计算时间。由于我的 R 初学者编程技能,我最终:-) 我们将非常感谢您的任何帮助或建议。预先非常感谢您。


本着“授人以鱼,不如授人以鱼”的精神,我将引导您完成这一点:

  1. 复制你的代码:你会把它搞砸的!

  2. 找到瓶颈:

    1a:使问题变小:

    Rep  <- 100
    df.expanded <- as.data.frame(replicate(nRep,sent$words))
    library(zoo)
    sent <- coredata(sent)[rep(seq(nrow(sent)),nRep),]
    

    1b:保留参考解决方案:您将更改代码,并且很少有活动比优化代码更能引入错误!

    sentRef <- sent
    

    并在代码末尾添加相同但已注释掉的内容,以记住您的参考文献在哪里。为了更容易检查您是否弄乱了代码,您可以在代码末尾自动测试它:

    library("testthat")
    expect_equal(sent,sentRef)
    

    1c:触发代码周围的分析器来查看:

    Rprof()
    SentimentScore2 <- unlist(lapply(sent$words, scoreSentence2))
    Rprof(NULL)
    

    1d:查看结果,以 R 为基数:

    summaryRprof()
    

    还有更好的工具,你可以检查包 轮廓R 或者 线教授

    线教授 是我选择的工具,这里有一个真正的附加值,可以将问题范围缩小到这两行:

    matchWords <- paste("\\<",wordsDF[x,1],'\\>', sep="") # matching exact words
    count <- length(grep(matchWords,sentence)) # count them
    
  3. Fix it.

    3.1 幸运的是,主要问题相当简单:您不需要将第一行放在函数中,只需将其移到前面即可。顺便说一下,这同样适用于你的paste0()。你的代码变成:

    matchWords <- paste("\\<",wordsDF[,1],'\\>', sep="") # matching exact words
    matchedWords <- paste0('\\s*\\b', wordsDF[,1], '\\b\\s*')
    
    # Sentiment score function
    scoreSentence2 <- function(sentence){
        score <- 0
        for(x in 1:nrow(wordsDF)){
            count <- length(grep(matchWords[x],sentence)) # count them
            if(count){
                score <- score + (count * wordsDF[x,2]) # compute score (count * sentValue)
                sentence <- gsub(matchedWords[x],' ', sentence) # remove matched words from wordsDF
                require(qdapRegex)
                # sentence <- rm_white(sentence)
            }
        }
        score
    }
    

    这将 1000 次重复的执行时间从
    5.64 秒至 2.32 秒。不错的投资!

    3.2 下一个漏洞是“count

    matchWords <- paste("\\<",wordsDF[,1],'\\>', sep="") # matching exact words
    matchedWords <- paste0('\\s*\\b', wordsDF[,1], '\\b\\s*')
    
    # Sentiment score function
    scoreSentence2 <- function(sentence){
        score <- 0
        for(x in 1:nrow(wordsDF)){
            count <- grepl(matchWords[x],sentence) # count them
            score <- score + (count * wordsDF[x,2]) # compute score (count * sentValue)
            sentence <- gsub(matchedWords[x],' ', sentence) # remove matched words from wordsDF
            require(qdapRegex)
            # sentence <- rm_white(sentence)
        }
        score
    }
    

这使得 0.18 秒或 31 倍快......

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

向量化 for 循环以加速 R 中的程序 的相关文章

随机推荐

  • 如何使用 Flask 和 Flask-login 传递“下一个”URL?

    的文档Flask 登录 https flask login readthedocs org en latest 谈论处理 下一个 URL 这个想法似乎是 用户前往 secret 用户被重定向到登录页面 例如 login 登录成功后 用户将被
  • 将 UIWebView 限制为特定 URL (Swift)

    我正在尝试开发一款 iOS 应用程序 该应用程序在 Swift 中具有 UIWebView 但是我需要它仅适用于一个域 并且在该 UIWebView 中单击的任何外部链接都将在 Safari 中打开 例如 所有链接http example
  • 延迟初始化和 deinit

    我想知道是否有可能在我的视图控制器中使用惰性属性并在deinit方法仅在初始化时才调用我的惰性属性的方法 下面是一些代码 fileprivate lazy var session MySession let session MySessio
  • Rails 4 - 具有简单形式的依赖字段的 JS

    我正在尝试在 Rails 4 中制作一个应用程序 我正在使用简单的表单作为表单 并且刚刚尝试使用 gem dependent fields rails 来隐藏或显示基于主要问题的表单字段的子集问题 我被卡住了 我已将 gem 添加到我的 g
  • Javascript 与 Firefox insideText 问题[重复]

    这个问题在这里已经有答案了 function OpenWindow anchor var toUsername anchor innerText window open ChatWindow aspx username toUsername
  • Objective c - 处理自定义 UITableViewCell 按钮的按钮触摸事件的最佳实践

    处理自定义按钮的按钮触摸事件的最佳实践是什么UITableViewCell 我的课程 MyViewController MyCustomCell 我可以想到三个选择 第一个选项 将按钮作为属性MyCustomCell 然后在其中添加一个目标
  • 如何将字典附加到 pandas 数据框?

    我有一组包含 json 文件的 url 和一个空的 pandas 数据框 其中的列表示 jsnon 文件的属性 并非所有 json 文件都具有 pandas 数据框中的所有属性 我需要做的是从 json 文件创建字典 然后将每个字典作为新行
  • 将 FFmpeg 与 Android-NDK 结合使用

    我想用FFmpeg with Android NDK我在这方面非常基础 我需要一些帮助 我之前在网上研究过这个主题 但没有得到令人满意的解决方案 1 我如何使用FFmpeg通过 Windows 操作系统 我不想使用Ubuntu 请不要建议
  • 允许在url重写中使用中文字符

    我写了 URL 重写规则
  • 在 GDB 中搜索源目录

    如何告诉 nix 中的 GDB 在单个目录中递归搜索源文件 例如 如果一个模块中有一些不同的构建块 a 是 b c d 的父目录 其中 b c d 是子目录 源文件分布在b c b中 我需要向 GDB 指定所有源文件都位于 a 父目录 中
  • 我应该使用 PhoneGap 而不是增加 Android SDK 吗?

    虽然我对 Java 很熟悉 但我在 Web 开发方面有更多的经验 我希望开始编写简单的 Android 游戏 我是否应该只使用 Javascript HTML 来编写所有内容 而忘记在 Java Android SDK 上进行升级 我想我的
  • AngularJS 单击时更改控制器中的部分内容

    我正在开发一个仪表板应用程序 其中同时显示一组模块 我想向这些模块添加多个 视图 例如 Github 模块的第一个视图是存储库列表 当您单击该模块中的存储库链接时 模块中的该视图将被替换为一个新屏幕 显示有关该存储库的所有详细信息 但是 我
  • ASP.Net MVC 3 登录和 Windows 身份验证

    我正在开发 ASP Net MVC 3 应用程序 并且有一个存储用户名及其密码的用户表 我创建了一个额外的 ADUsername 存储 Active Directory 的域 用户名 我正在尝试执行以下操作 从 Intranet 运行应用程
  • Cl.exe 返回错误代码 D8050

    我在使用 microsoft Visual Studio Ultimate 2013 全新安装 Windows 8 时出现以下错误 cl Command line error D8050 cannot execute C Program F
  • 如何通过 urlfetchapp 发送带有有效负载中的数组的 post 请求

    我需要模拟从 html 表单到页面的 post 请求 我需要知道如何在有效负载中正确发送数组 提前致谢 我有简单的 html 代码 目标页面将以这种方式收到提交 args data files form Link picturelink1
  • 重定向到文件后使用 cout 或 cerr 输出到控制台

    将 cout 或 cerr 重定向到文件非常容易 我可以用它来将第三方输出重定向到文件 但是 当我将第三方输出重定向到文件后 我自己如何使用 cout 输出到控制台 我是 RAII 的忠实粉丝 所以我曾经编写过这个小助手类 它将重定向流 直
  • 使用依赖网络的代码进行单元测试

    我正在努力更好地对我的代码进行单元测试 但现在我正在编写大量处理远程系统的代码 SNMP WMI 之类的 对于大多数类 我可以模拟对象来测试它们 但是如何处理真实系统的单元测试呢 例如 如果我的类出去并获取服务器的 Win32 Logica
  • Python Selenium 等待任何文本

    我有一个硒测试 需要等到填充任何文本而不是精确的文本字符串匹配 我了解到text to be present in element text to be present in element value可以用于这种类型的目的 但我可能需要像
  • iOS 中解析 JSON 与解析 XML

    设想 我正在开发一个解析器 用于在发出请求后从服务器发回的数据 数据的格式是 JSON 或 XML 问题 是否有理由选择其中一种格式而不是另一种 解析 json 和解析 xml 哪个更快 谢谢大家 当 JSON 成为首选时 通常是因为它要短
  • 向量化 for 循环以加速 R 中的程序

    我正在寻找一些简单的矢量化方法for loop在 R 中 我有以下数据框 其中包含句子和两本正面和负面单词的字典 Create data frame with sentences sent lt data frame words c jus