【问题标题】:Detect text language in R检测 R 中的文本语言
【发布时间】:2011-12-26 02:08:08
【问题描述】:

我有一个推文列表,我想只保留英文推文。

我该怎么做?

【问题讨论】:

    标签: r text-mining


    【解决方案1】:

    R 中的一种方法是保留英文单词的文本文件。我有其中几个,其中一个来自http://www.sil.org/linguistics/wordlists/english/。获取 .txt 文件后,您可以使用此文件来匹配每条推文。比如:

    lapply(tweets, function(x) EnglishWordComparisonList %in% x)
    

    您希望有一些阈值百分比来确定它是否是英语(我随意选择了 0.06)。

    EnglishWordComparisonList<-as.vector(source(path to the list you downloaded above))
    
    Englishinator<-function(tweet, threshold = .06) {
        TWTS <- which((EnglishWordComparisonList %in% tweet)/length(tweet) > threshold)
        tweet[TWTS]
        #or tweet[TWTS,] if the original tweets is a data frame
    }
    
    lapply(tweets, Englishinator)
    

    我实际上并没有使用过这个,因为我在研究中使用英语单词列表的方式大不相同,但我认为这会起作用。

    【讨论】:

    • 您能否进一步详细说明阈值百分比?
    【解决方案2】:

    还有一个运行良好的 R 包,名为“franc”。虽然它比其他的慢,但我对它的体验比使用 cld2 尤其是 cld3 更好。

    【讨论】:

      【解决方案3】:

      上一个答案中的cldr 包在 CRAN 上不再可用,并且可能难以安装。但是,Google(Chromium 的)cld 库现在可以通过其他专用包在 R 中使用,cld2cld3

      在用多种欧洲语言测试了数千条推文之后,我可以说在可用选项中,textcat 是迄今为止最不可靠的。使用textcat,我也经常收到错误地将推文检测为“middle_frisian”、“rumantsch”、“sanskrit”或其他不寻常的语言。它可能与其他类型的文本相对较好,但我认为textcat 对于推文来说非常糟糕。

      cld2 似乎总体上还是比cld3 好。如果您想要一种仅包含英文推文的安全方式,您仍然可以同时运行 cld2cld3 并仅保留两者都识别为英文的推文。

      这是一个基于 Twitter 搜索的示例,该搜索通常提供多种不同语言的结果,但总是包含一些英文推文。

      if (!require("pacman")) install.packages("pacman") # for package manangement
      pacman::p_load("tidyverse") 
      pacman::p_load("textcat")
      pacman::p_load("cld2")
      pacman::p_load("cld3")
      pacman::p_load("rtweet")
      
      punk <- rtweet::search_tweets(q = "punk") %>% mutate(textcat = textcat(x = text), cld2 = cld2::detect_language(text = text, plain_text = FALSE), cld3 = cld3::detect_language(text = text)) %>% select(text, textcat, cld2, cld3)
      View(punk)
      
      # Only English tweets
      punk %>% filter(cld2 == "en" & cld3 == "en")
      

      最后,如果这个问题与推文特别相关,我也许应该补充一点:Twitter 通过 API 为推文提供了自己的语言检测,而且它似乎非常准确(可以理解,对于非常短的推文来说不太准确)。因此,如果您运行rtweet::search_tweets(q = "punk"),您将看到生成的 data.frame 包含一个“lang”列。如果您通过 API 获取推文,那么您可能更信任 Twitter 自己的检测系统,而不是上面建议的替代解决方案(对于其他文本仍然有效)。

      【讨论】:

        【解决方案4】:

        tl;drcld2 是迄今为止最快的(cld3 x22textcat x118,手工制作解 x252)

        这里有很多关于准确性的讨论,这对于推文是可以理解的。但是速度呢?

        这是cld2cld3textcat 的基准。

        我还加入了一些我写的幼稚函数,它计算文本中停用词的出现次数(使用tm::stopwords)。

        我认为对于长文本我可能不需要复杂的算法,并且对多种语言进行测试可能是有害的。最后,我的方法最终是最慢的(很可能是因为打包的方法在 C 中循环。

        我把它留在这里,这样我就可以把时间留给那些有相同想法的人。我预计Tyler RinkerEnglishinator 解决方案也会很慢(仅测试一种语言,但要测试更多的单词和类似的代码)。

        detect_from_sw <- function(text,candidates){
          sapply(strsplit(text,'[ [:punct:]]'),function(y)
            names(which.max(sapply(candidates,function(x) sum(tm::stopwords(x) %in% y))))
          )
        }
        

        基准

        data(reuters,package = "kernlab") # a corpus of articles in english
        length(reuters)
        # [1] 40
        sapply(reuters,nchar)
        # [1] 1311  800  511 2350  343  388 3705  604  254  239  632  607  867  240
        # [15]  234  172  538  887 2500 1030  538 2681  338  402  563 2825 2800  947
        # [29] 2156 2103 2283  604  632  602  642  892 1187  472 1829  367
        text <- unlist(reuters)
        
        microbenchmark::microbenchmark(
          textcat = textcat::textcat(text),
          cld2 = cld2::detect_language(text),
          cld3 = cld3::detect_language(text),
          detect_from_sw = detect_from_sw(text,c("english","french","german")),
          times=100)
        
        # Unit: milliseconds
        # expr                 min         lq      mean     median         uq         max neval
        # textcat        212.37624 222.428824 230.73971 227.248649 232.488500  410.576901   100
        # cld2             1.67860   1.824697   1.96115   1.955098   2.034787    2.715161   100
        # cld3            42.76642  43.505048  44.07407  43.967939  44.579490   46.604164   100
        # detect_from_sw 439.76812 444.873041 494.47524 450.551485 470.322047 2414.874973   100
        

        注意textcat 的不准确之处

        我无法评论 cld2cld3 的准确性(@giocomai 声称 cld2 在他的回答中更好),但我确认 textcat 似乎非常不可靠(在几个地方提到了这个页)。除了textcat 分类为西班牙语的这一篇之外,所有文本均已通过上述所有方法正确分类:

        “阿根廷原油产量在 1987 年 1 月下降了 10.8% Yacimientos Petroliferos Fiscales 称,1232 万桶,1986 年 1 月为 13.81 万桶。 \n 1987 年 1 月自然 天然气产量总计 11.5 亿立方米,高于 3.6% Yacimientos Petroliferos Fiscales 补充说,1986 年 1 月生产了 11.1 亿立方米。 \n路透社”

        【讨论】:

          【解决方案5】:

          试试http://cran.r-project.org/web/packages/cldr/,它将 Google Chrome 的语言检测功能引入 R。

          #install from archive
          url <- "http://cran.us.r-project.org/src/contrib/Archive/cldr/cldr_1.1.0.tar.gz"
          pkgFile<-"cldr_1.1.0.tar.gz"
          download.file(url = url, destfile = pkgFile)
          install.packages(pkgs=pkgFile, type="source", repos=NULL)
          unlink(pkgFile)
          # or devtools::install_version("cldr",version="1.1.0")
          
          #usage
          library(cldr)
          demo(cldr)
          

          【讨论】:

          • 我看到这个包已从 CRAN 中删除。
          • 您仍然可以从cran.us.r-project.org/src/contrib/Archive/cldr 下载它(我没有时间进行修改以使其与CRAN 的新C 语言要求兼容)
          • 如果你有编译工具你也可以使用 devtools::install_version("cldr",version="1.1.0") 来安装
          • @aykutfirat 您能否分享在 Ubuntu 或 Fedora 中编译它所需的库列表?或者至少如果有一些在这方面不寻常的必需包?我在尝试安装时收到的错误消息没有提供明确的提示(至少,我无法真正理解)
          • 嗯.. cldr::detectLanguage("Their debut album") == 100% 印尼语
          【解决方案6】:

          textcat 包就是这样做的。它可以检测 74 种“语言”(更准确地说,是语言/编码组合),更多的是其他扩展。详细信息和示例在这篇免费提供的文章中:

          Hornik, K., Mair, P., Rauch, J., Geiger, W., Buchta, C. 和 Feinerer, I. The textcat Package for n-Gram Based Text Categorization 在 R. Journal of Statistical Software, 52, 1-17。

          这是摘要:

          识别所使用的语言通常是大多数情况下的第一步 自然语言处理任务。在多种多样的语言中 文献中讨论的识别方法,采用 Cavnar 和 Trenkle (1994) 的文本分类方法 字符 n-gram 频率特别成功。这 论文介绍了基于 n-gram 文本的 R 扩展包 textcat 实现 Cavnar 和 Trenkle 方法的分类 以及旨在消除冗余的简化 n-gram 方法 的原始方法。获得的多语种语料库 可用于选择主题的 Wikipedia 页面用于 说明包的功能和性能 提供语言识别方法。

          这是他们的一个例子:

          library("textcat")
          textcat(c(
            "This is an English sentence.",
            "Das ist ein deutscher Satz.",
            "Esta es una frase en espa~nol."))
          [1] "english" "german" "spanish" 
          

          【讨论】:

          • textcat() 返回了许多错误分类:我只是在 800 篇我知道的德语或英语的学术文章摘要上运行它。尽管如此,textcat 将 3 归为拉丁语,将 3 归为法语 (?!),将 2 归为加泰罗尼亚语 (?!?!)。然而,@aykutfirat 提出的 cldr-package 在所有文本中都恰到好处,甚至提出了第二和第三个替代方案。
          • 对于一种看起来既快又脏(ngram 匹配)的方法,我想说的错误率还不错
          【解决方案7】:

          我不确定 R,但有几个其他语言的库。您可以在此处找到其中的一些收集:

          http://www.detectlanguage.com/

          最近还有一个有趣的项目:

          http://blog.mikemccandless.com/2011/10/language-detection-with-googles-compact.html

          使用此库制作 Twitter 语言地图:

          http://www.flickr.com/photos/walkingsf/6277163176/in/photostream

          如果你找不到 R 的库,我建议考虑通过 webservice 使用远程语言检测器。

          【讨论】:

          • 谢谢@Laurynas!我一直在等待 R 特定的答案,但你的答案很好开始。但是,Google Translate API(即 www.detectlanguage.com)将于 2011 年 12 月 1 日停用(Google 将其转变为付费服务)
          • 没有问题 :) 如果 Google 翻译将被禁用,您可以在 detectlanguage.com 上使用网络服务。我今天发布了。
          • 是的,效果很好!有没有可能我在大约 10 小时前刚刚检查过这个网站,并且当时它是基于谷歌翻译的? :)
          • 是的,它使用谷歌翻译作为翻译示例(我把它移到这里:detectlanguage.com/translate)。在您发表评论后,我创建了基于 C 语言检测器(而不是 Google 翻译)的网络服务。
          • @Laurynas detecklanguage.com 网络服务在 24 小时内允许的最大请求数是多少?
          猜你喜欢
          • 2016-07-04
          • 2021-10-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-12-30
          • 1970-01-01
          • 2018-06-02
          相关资源
          最近更新 更多