首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >如何用R进行中文分词?

如何用R进行中文分词?

作者头像
用户7652506
发布2020-10-23 16:25:08
1.2K0
发布2020-10-23 16:25:08
举报

在前面

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拼回原数据集,最终效果如图:

代码如下(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)]

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2016-05-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 大猫的R语言课堂 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档