前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >R语言:通过jiebaR提升正则匹配效率

R语言:通过jiebaR提升正则匹配效率

作者头像
用户7652506
发布2022-01-07 15:38:32
4010
发布2022-01-07 15:38:32
举报

问题提出

大家会不会经常遇到这样的情况,需要在一系列的目标文本中,匹配搜索一系列特征文本,且这些特征文本可能在该某一目标文本中重复出现。例如如下数据集:

其中数据集news为上市公司新闻数据,变量NewsID为新闻的id编号;FullDeclareDate为新闻公布时间;TitleKeyWords为新闻的标题和关键词。

代码语言:javascript
复制
news[1:5]

NewsID

FullDeclareDate

TitleKeyWords

57285603

2/3/2010 12:00

富机达能正式挂牌

57463469

1/3/2010 15:22

新能源过剩事出有因 多晶硅风电获准松绑新能源,多晶硅,风电,松绑,

57463473

1/3/2010 15:19

近9年元旦后首个交易日沪指走势一览 虎年怎开盘元旦,交易日,沪指,走势,

57463477

1/3/2010 15:13

中央将下发2010年一号文件 出台新强农惠农政策一号文件,惠农新政,农民,收入,胡锦涛,

57463479

1/3/2010 16:06

2010年首份年报12日亮相 1月共20家公司公布年报年报,上市公司,国海证券,

数据集id为上市公司股票代码及名称,stkcd为上市公司股票代码,name为上市公司股票名称。

注:此处为了处理的方便,已经将上市公司中带有字母的部分进行了去除,例如带有字母A万科A,以及带有ST字样的股票代码。 ”

代码语言:javascript
复制
id[1:5]

stkcd

name

000001

平安银行

000002

万科

000004

国农科技

000005

世纪星源

000006

深振业

如果需要对上市公司相关新闻进行研究,首先将相关上市公司的相关新闻进行筛选和标记。在本例中转化为代码需求,则需要在news的新闻标题和关键词中寻找是否存在某一个上市公司的名称,即需要将数据集id中的name字段匹配到数据集news中的TitleKeyWords字段中,看是否有一个或多个上市公司名称存在新闻标题中。

具体方法

1.正则表达式

对于文本的分析首先会想到的是正则表达式,利用正则表达式进行处理的主要思想在于:

通过构建正则标准,对每一个特征文本在每一个目标文本中的存在性进行遍历。

对如下代码进行解读可以发现,利用正则表达式进行处理有三个关键点:

  • 需要将特征文本进行进一步处理。由于需要进行每一个上市公司的相关名称的遍历判断,则需要对每一个名称进行“or”操作。paste(id[["name"]], collapse = "|")代码,将上市公司名称的向量进行了整合,并在每一个名称用符号|进行连接,从而进行补集操作,让至少对应一个上市公司名称的文本能够提取。
  • 需要用到stringr包中str_extract_all这样一个函数。相比于普通的str_extract函数,在进行字符串提取时,不会仅仅只匹配第一个相关的项目,而是会把判断条件中的所有的潜在选项都进行匹配,从而对每一个目标文本生成一个相应的提取向量,最后以list形式输出。
  • 需要对每一条目标文本生成的提取向量进行展开。在运用完str_extract_all函数之后,需要对生成的list,按照NewsID变量进行展开,故而在之后用到%>% unlist()by = .(NewsID)
代码语言:javascript
复制
library(stringr)
news_regex <- news[, .(name = str_extract_all(TitleKeyWords, paste(id[["name"]], collapse = "|"))%>% unlist()), by = .(NewsID)
    ][order(NewsID), .SD]
news_regex[1:5]

NewsID

name

57463479

国海证券

57463969

酒鬼酒

57463973

岳阳兴长

57463975

华闻传媒

57463981

广东鸿图

2. 分词包构造词典

利用分词包jiebaR进行分词处理的思想,主要在于:

将上市公司的名称当作一个新加入的词典,加入分词规则中,对目标文本整体进行分词,而后筛选除符合标准的分词结果。

对如下代码进行解读可以发现三个关键点:

  • 需要将特征文本添加为词典中的词。为了将上市公司名称添加至词典中,首先需要添加一个分词的引擎,运用worker函数添加一个引擎命名为cutter,而后用new_user_word()函数将id[["name"]]添加到分词引擎cutter中。
  • 需要利用分词函数进行分词。利用分词函数segment,导入分词引擎cutter,对TitleKeyWords进行分词。
  • 需要将原有的特征文本与分词后的目标文本文件进行匹配。利用data.table包中的表合并语法进行操作,最后没有匹配的项目不显示nomatch = 0
代码语言:javascript
复制
library(jiebaR)
cutter <- worker()
new_user_word(cutter, id[["name"]])
news_dict <- id[, .SD, .SDcols = c("name")
    ][news[, .(name = segment(TitleKeyWords, cutter)), by = .(NewsID)
    ], on = .(name), nomatch = 0
    ][order(NewsID), unique(.SD)]
news_dict[1:5]

TRUE

name

NewsID

国海证券

57463479

酒鬼酒

57463969

岳阳兴长

57463973

华闻传媒

57463975

广东鸿图

57463981

效率对比

利用正则表达式二者之间是否存在一定的差异,下面分别进行运行时间的测度。

100条记录

代码语言:javascript
复制
# 正则法
system.time(
    news_regex <- news[1:100, .(name = str_extract_all(TitleKeyWords, paste(id[["name"]], collapse = "|"))%>% unlist()), by = .(NewsID)
        ][order(NewsID), .SD]
)
代码语言:javascript
复制
   user  system elapsed 
   0.58    0.00    0.58
代码语言:javascript
复制
# 分词法
system.time(
    news_dict <- id[, .SD, .SDcols = c("name")
        ][news[1:100, .(name = segment(TitleKeyWords, cutter)), by = .(NewsID)
        ], on = .(name), nomatch = 0
        ][order(NewsID), unique(.SD)]
)
代码语言:javascript
复制
   user  system elapsed 
   0.08    0.03    0.11

1000条记录

代码语言:javascript
复制
# 正则法
system.time(
    news_regex <- news[1:1000, .(name = str_extract_all(TitleKeyWords, paste(id[["name"]], collapse = "|"))%>% unlist()), by = .(NewsID)
        ][order(NewsID), .SD]
)
代码语言:javascript
复制
   user  system elapsed 
   5.50    0.02    5.68
代码语言:javascript
复制
# 分词法
system.time(
    news_dict <- id[, .SD, .SDcols = c("name")
        ][news[1:1000, .(name = segment(TitleKeyWords, cutter)), by = .(NewsID)
        ], on = .(name), nomatch = 0
        ][order(NewsID), unique(.SD)]
)
代码语言:javascript
复制
   user  system elapsed 
   0.30    0.14    0.50

10000条记录

代码语言:javascript
复制
# 正则法
system.time(
    news_regex <- news[1:10000, .(name = str_extract_all(TitleKeyWords, paste(id[["name"]], collapse = "|"))%>% unlist()), by = .(NewsID)
        ][order(NewsID), .SD]
)
代码语言:javascript
复制
   user  system elapsed 
  61.44    0.14   68.87
代码语言:javascript
复制
# 分词法
system.time(
    news_dict <- id[, .SD, .SDcols = c("name")
        ][news[1:10000, .(name = segment(TitleKeyWords, cutter)), by = .(NewsID)
        ], on = .(name), nomatch = 0
        ][order(NewsID), unique(.SD)]
)
代码语言:javascript
复制
   user  system elapsed 
   2.40    2.13    4.84

通过对比上述运行时间可以发现,随着样本量的增大,利用分词包进行特征文本匹配的效率的优势逐渐凸显,更加建议在进行多特征文本匹配时,利用分词法进行操作!!

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

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 问题提出
    • 具体方法
      • 1.正则表达式
      • 2. 分词包构造词典
    • 效率对比
      • 100条记录
      • 1000条记录
      • 10000条记录
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档