简介:通过IK分词器分词并生成词云。
本文主要介绍如何通过 IK 分词器进行词频统计。使用分词器对文章的词频进行统计,主要目的是实现如下图所示的词云功能,可以找到文章内的重点词汇。后续也可以对词进行词性标注,实体识别以及对实体的情感分析等功能。
词频统计服务具体模块如下:数据输入:文本信息数据输出:词 - 词频(TF-IDF等) - 词性等内容使用的组件:分词器、语料库、词云展示组件等功能点:白名单,黑名单,同义词等
现存的中文分词器有 IK、HanLP、jieba 和 NLPIR 等几种,不同分词器各有特点,本文使用 IK 实现,因为 ES 一般使用 medcl 等大佬封装的 IK 分词器插件作为中文分词器。 由于 ES 的 IK 分词器插件深度结合了 ES,仅对文本分词使用不到 ES 的内容,所以文本采用申艳超大佬版本的 IK。
1. IK 分词统计代码IK 的代码相对比较简单,东西不多,将 String 拆分为词并统计代码如下:
- 单纯统计词频:
/**
* 全文本词频统计
*
* @param content 文本内容
* @param useSmart 是否使用 smart
* @return 词,词频
* @throws IOException
*/
private static Map countTermFrequency(String content, Boolean useSmart) throws IOException {
// 输出结果 Map
Map frequencies = new HashMap();
if (StringUtils.isBlank(content)) {
return frequencies;
}
DefaultConfig conf = new DefaultConfig();
conf.setUseSmart(useSmart);
// 使用 IKSegmenter 初始化文本信息并加载词典
IKSegmenter ikSegmenter = new IKSegmenter(new StringReader(content), conf);
Lexeme lexeme;
while ((lexeme = ikSegmenter.next()) != null) {
if (lexeme.getLexemeText().length() > 1) {// 过滤单字,也可以过滤其他内容,如数字和单纯符号等内容
final String term = lexeme.getLexemeText();
// Map 累加操作
frequencies.compute(term, (k, v) -> {
if (v == null) {
v = 1;
} else {
v += 1;
}
return v;
});
}
}
return frequencies;
}
- 统计词频和文档频率:
/**
* 文本列表词频和词文档频率统计
*
* @param docs 文档列表
* @param useSmart 是否使用只能分词
* @return 词频列表 词-[词频,文档频率]
* @throws IOException
*/
private static Map countTFDF(List docs, boolean useSmart) throws IOException {
// 输出结果 Map
Map frequencies = new HashMap();
for (String doc : docs) {
if (StringUtils.isBlank(doc)) {
continue;
}
DefaultConfig conf = new DefaultConfig();
conf.setUseSmart(useSmart);
// 使用 IKSegmenter 初始化文本信息并加载词典
IKSegmenter ikSegmenter = new IKSegmenter(new StringReader(doc), conf);
Lexeme lexeme;
// 用于文档频率统计的 Set
Set terms = new HashSet();
while ((lexeme = ikSegmenter.next()) != null) {
if (lexeme.getLexemeText().length() > 1) {
final String text = lexeme.getLexemeText();
// 进行词频统计
frequencies.compute(text, (k, v) -> {
if (v == null) {
v = new Integer[]{1, 0};
} else {
v[0] += 1;
}
return v;
});
terms.add(text);
}
}
// 进行文档频率统计:无需初始化 Map,统计词频后 Map 里面必有该词记录
for (String term : terms) {
frequencies.get(term)[1] += 1;
}
}
return frequencies;
}
2. 获取词云 TopN 个词
获取 TopN 个词用于词云展示有多种排序方式,可以直接根据词频、文档频率或者 TF-IDF 等算法进行排序,本文仅根据词频求取 TopN。M 个数字获取 TopN 有以下算法:
- M 小 N 小:快速选择算法
- M 大 N 小:小顶堆
- M 大 N 大:归并排序
本文采用小顶堆方式实现,对应JAVA中的优先队列数据结构 PriorityQueue:
/**
* 按出现次数,从高到低排序取 TopN
*
* @param data 词和排序数字对应的 Map
* @param TopN 词云展示的 TopN
* @return 前 N 个词和排序值
*/
private static List order(Map data, int topN) {
PriorityQueue priorityQueue = new PriorityQueue(data.size(), new Comparator() {
@Override
public int compare(Map.Entry o1, Map.Entry o2) {
return o2.getValue().compareTo(o1.getValue());
}
});
for (Map.Entry entry : data.entrySet()) {
priorityQueue.add(entry);
}
//TODO 当前100词频一致时(概率极低)的处理办法,if( list(0).value == list(99).value ){xxx}
List list = new ArrayList();
//统计结果队列size和topN值取较小值列表
int size = priorityQueue.size() = '0' && input = 'a' && input = 'A' && input
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?