如何用R进行中文分词?

Posted 大猫的R语言课堂

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何用R进行中文分词?相关的知识,希望对你有一定的参考价值。

在前面
Hello亲耐的小伙伴们!新一期的大猫课堂又和大家见面了。针对前几期课程,不少童鞋向大猫提出了一些非常好的建议,例如:把需要用到的包明确写出来,中间过程不要省略,增加一些基础知识的讲解等。 大猫在这里由衷感谢所有提出建议的小伙伴们,同时向上几期的不尽人意之处表示歉意,我会继续努力哒!

期目标
从本期开始我们将开始一个关于用R进行文本挖掘的系列教程,主要包括 用jiebaR进行分词、 建立自定义停用词库、 用tm建立语料库,以及 一些常见的文本挖掘算法应用。本期,大猫先教大家 如何使用jiebaR进行分词!(word segmanetation by R)

本期课堂所介绍的代码主要用于演示,对于处理小规模文本数据有效,但是如果你的文本数据“比较脏”,或者你希望写出一个R高手才能写出的代码,欢迎参考文末最后的终极版分词代码。

前准备
1)安装jiebaR,可以用如下代码:
install.packages("jiebaR")
jiebaR的中文名称是“结巴分词”。不光在R中,在Python等语言中,结巴分词也是最优秀、使用最广的分词包之一。jiebaR是jieba分词的R版本,使用了Rcpp进行编写,充分利用了C++高效的特点。目前,结巴分词在C++、R、Python平台下都有对应版本,无论你采用那个平台,都能获得接近一致的体验。

2)安装data.table。data.table是当前R中最强大的数据处理包之一,在大猫课堂中,所有的数据处理都要使用到data.table。安装代码如下:
install.packages("data.table")

3)安装包magrittr
我们在这里只用到magrittr包的一个功能,即"%>%"操作符。"%>%"的功能是使得代码易读,避免“夹心函数”的出现,小伙伴们看了以下例子就懂了。
# example of %>%
> sqrt(floor(3.23))
# which is equal to:
> floor(3.23) %>% sqrt()

4)安装包stringr
stringr是R中用于文本处理的常用包,它把许多常见的文本处理函数重新打包,并赋予了规律性的名字,比如所有字符函数都用“str_”做前缀,字符拼接函数就是“str_c”。

5)载入上文所述包
library(jiebaR)
library(data.table)
library(magrittr)
library(stringr)

6)初始化jiebaR
jiebaR为了能够工作,需要手动初始化分词器。大家可以把分词器想象成一个自定义的分词函数,这个函数包含了指定的 分词模型(一般情况下使用默认的混合模型就可以了)以及停用词等。这一步只需一行代码(关于停用词字典我们放到下节课z):
# initialize worker
mixseg <- worker()

在建立分词器mixseg后,我们就可以用它来完成一些简单的分词工作了:
# example of worker
> mixseg["华山海拔不到3000米"]
[1] "华山" "海拔" "不到" "3000" "米"  

虽然已经能对单句进行分词,但分词的结果是一个多维(每个词都是一维)的 字符向量。我们希望最终的结果是 一个 字符,其中每个词都用空格分割,就像这样:
[1] "华山 海拔 不到 3000 米"
如何做到这点呢?另外,如何在数据集中批量对文本分词?Let's move on!

备示例数据集
为了尽可能通俗易懂,我们的示例数据集中只放三条文本,预览如下:

生成示例数据集的代码如下:
# create sample dataset

text <- c("今天天气真好", "五一的时候西湖挤爆了", "我怀念西安的裤带面和梆梆肉")

dt <- data.table(text = text)

单个句子分词
我们首先建立对单个句子进行分词的函数seg_x,然后在下一步中使用sapply函数将seg_x批量使用在数据集中。对单个句子分词的函数是:
seg_x <- function(x) {
  str_c(mixseg[x], collapse = " ")
}

> seg_x("五一的时候西湖挤爆了 ")
[1] "五一 的 时候 西湖 挤爆 了" 
我们使用str_c函数把分词的结果由许多分散的词拼成了一个长的字符,collapse = " "表示词与词之间用空格进行分割

数据集进行分词
如果要对数据集进行分词,需要用到sapply函数。关于sapply函数的知识小伙伴们请课后学习,因为apply族函数的知识讲上一天一夜都讲不完,并且它又是R中最重要的函数系列。

我们对数据集分词的思路是:首先把文本向量text进行分词,命名为text.seg,然后把text.seg拼回原数据集,最终效果如图:
如何用R进行中文分词?

代码如下(2行):
x.out <- sapply(dt$text, seg_x, USE.NAMES = F)

dt[, text.seg := x.out]
其中sapply的作用是 ,对于字符向量text中的每个元素都应用seg_x函数进行分词,然后把结果拼成一个长字符向量,其元素个数和text一致。

另外,USE.NAMES = F的作用是让生成的x.out变量不带名称,否则其每个元素都会被赋予一个名称,浪费了空间又拖慢处理速度(小伙伴们可以试一下不加会怎么样)。

第二行代码中,dt[, text.seg := x.out]的作用是:在数据集dt中新生成一个变量text.seg,其值等于向量x.out。

极版代码
OK,到此为止,一个完整的中文分词流程就介绍完了。但是, 以上代码仅适用于一般情况,对于一些复杂的文本,特别是通过爬虫从网上获得的文本,常常会遇到许多意想不到的问题。大猫在下面放上自己在实际中使用的代码,其中会涉及到一些高阶的R编程知识,例如vapply函数,tryCatch函数等,小伙伴们可以课后思考学习哦。
# 分词 --------------------------------------------------
# 函数:make_seg_x
make_seg_x <- function(x) {
    stopifnot(is.character(x))
    str_replace_all(x, "[//.///]", " ")
}

# 函数:seg_x
seg_x <- function(x) {
    stopifnot(is.character(x), length(x) == 1)
    out <- tryCatch(str_c(mixseg[x], collapse = " "),
             error = function(c) {
                 cat(c$message, ": ", x, "\n")
                 c$message
             })
    if (length(out) == 1) {
        out
    } else if (length(out) == 0) {
        ""
    }
}

# 函数:seg_dt
seg_dt <- function(dt, x, tick.by) {
    stopifnot(is.character(x), is.integer(tick.by))
    x.seg <- vapply(make_seg_x(dt[[x]]), show_process_every(tick.by, seg_x),
                    character(1), USE.NAMES = F)
    dt[, str_c(x, ".seg") := x.seg, with = F]
}

# 建立分词器(包括停用词)
mixseg <- worker(dict = DICTPATH, user = use.dict.path, stop_word = stop.dict.path)

# 进行分词
# post数据集分词
system.time({
    seg_dt(post, "text", tick.by = 20000L);
    sv(post)
}) # seg_dt is a function modify in place
pred <- post[!(text.seg %in% c("Cannot open file", "")),
             .(id, pubdate, text.seg)]

 
大猫的R语言课堂

我是 大猫,我是一个高中读文科但却在代码、数学的路上狂奔不止的Finance Ph. D Candidate。

我的微信号是iRoss2007

我的 R语言课堂关注R语言、数据挖掘以及经济金融学。

我与大家分享我的知识,我相信独乐乐不如众乐乐

我还有许多 好玩的计划。

更多的精彩内容正在路上。
长按二维码关注

以上是关于如何用R进行中文分词?的主要内容,如果未能解决你的问题,请参考以下文章

如何用python和jieba分词,统计词频?

如何用Python做中文分词?

R语言文本挖掘—文本分词

如何用 Python 中的 NLTK 对中文进行分析和处理

jieba分词(R vs. python)

如何用Python做词云