Overview

涉及的知识点

  • tidy形式的转换
  • 断句
  • 断词

会用到的packages

会用到的packages和函数:

  • library(dplyr):整合所有在前处理数据会常用的“逻辑”,加入pipeline的概念

    • select():挑选特定column出来
    • filter():自订条件滤掉column中的资料
    • arrange():调整row排列顺序
    • mutate():以现有的column资料做运算,形成新的column
    • summarise():将目前的资料做统计运算,形成统计结论
    • tibble():将典型的字符向量变成 tidy 文本数据集
  • library(jiebaR):用于断词(ref:https://zhuanlan.zhihu.com/p/35846130

    • worker():初始化断词引擎
      • stop_word=”stop_word.txt”:停用词
      • user=”xxx.txt”:自定义词库:可以自己定义,也可以借用搜狗细胞词库,有大量专业领域词汇
      • bylines = TRUE:不保留标点符号
      • 注意:user=”xxx.txt” 以及 stop_word=”stop_word.txt”的txt档案一定要是UTF-8编码的格式
    • segment():断词(一般配合supply来写成function使用)
    • filter_segment():在前面worker()过滤后的基础上,再次过滤
  • library(tidytext)

    • unnest_tokens():将文本拆分成tokens,转换成tidy的格式
  • library(tidyr):重新定义资料框,留下绘图需要的点

    • spread():
    • gather():
    • separate(): 将 info 栏位以分号分割成三个栏位,并且直接放进原 data frame 中

实作

读取资料以及packages

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 避免中文乱码
Sys.setlocale(category = "LC_ALL", locale = "zh_TW.UTF-8")

# 载入资料
library(dplyr)
library(tidytext)
library(wordcloud2)
library(data.table)
library(ggplot2)
library(wordcloud)
library(tidyr)
library(jiebaR)

# 把文章和留言读进来
MetaData = read.csv('./data/PTTcoin_articleMetaData.csv',encoding = 'UTF-8')
Reviews = read.csv('./data/PTTcoin_articleReviews.csv',encoding = 'UTF-8')

MetaData$sentence <- as.character(MetaData$sentence)
Reviews$cmtContent <- as.character(Reviews$cmtContent)

# 挑选文章对应的留言
Reviews = left_join(MetaData, Reviews[,c("artUrl", "cmtContent")], by = "artUrl")

# 查看读进来的资料
str(Reviews)

读进来的原始资料

断词

初始化断词引擎

1
2
# 初始化断词引擎
jieba_tokenizer <- worker(stop_word = "./stop_words.txt",user="./user_dict.txt")

我们将设置好的断词引擎加入我们写好的断词函式中,方便在在我们资料格式中断词

1
2
3
4
5
6
7
8
# 自定义断词函式
chinese_tokenizer <- function(t) {
lapply(t, function(x) {
tokens <- segment(x, jieba_tokenizer)
tokens <- tokens[nchar(tokens)>1]
return(tokens)
})
}
1
2
3
# 将原始资料断词
tokens <- MetaData %>%
unnest_tokens(word, sentence, token=chinese_tokenizer)
1
2
3
4
5
6
7
8
9
10
11
12
# 格式化日期栏位
tokens$artDate <- tokens$artDate %>% as.Date("%Y/%m/%d")

# 过滤特殊字元
tokens <- tokens %>%
filter(!(word %in% stop_words)) %>% # 去掉停用字里的一些词汇
filter(!grepl('[[:punct:]]',word)) %>% # 去标点符号
filter(!grepl("['^0-9a-z']",word)) %>% # 去英文、数字
filter(nchar(.$word)>1)
# select(-artDate, -artUrl)

head(tokens, 20)

查看出现词

文字云

1
2
3
4
5
6
7
8
9
# 文字云
# 计算词汇的出现次数,如果词汇只有一个字则不列入计算
tokens_count <- tokens %>%
filter(nchar(.$word)>1) %>%
group_by(word) %>%
summarise(sum = n()) %>%
filter(sum>10) %>%
arrange(desc(sum))
head(tokens_count, 30)

出现前30的词

1
2
3
tokens_count %>% 
filter(word!=c("比特币","原文"))%>%
# wordcloud2()

词性的标注(NER)

那么如果我们想知道里面的名词都有哪些?

我们就需要更改worker()中type的参数,改为worker(type=”tag”),就可以用jieba来标记中文的词性了

1
2
3
4
5
6
7
8
9
10
11
12
# 初始化词性标注引擎
tag_cuter <- worker(type="tag", stop_word="./stop_words.txt",user="./user_dict.txt")

raw_text <- "在狗狗币的市场中有一只巨鲸持有着30%的狗狗币,有一些线索指出这个持有者很有可能就是马斯克"
look <- segment(raw_text, tag_cuter)

# 标注词性的断词函式
get_noun = function(x){
index = names(x) %in% c("n","nr","nr1","nr2","nrj","nrf","ns","nsf","nt","nz","nl","ng")
x[index]
}
get_noun(look)

词性的标注

1
2
3
4
5
6
7
8
# 自定义断词函式
tag_tokenizer <- function(t) {
lapply(t, function(x) {
tokens <- segment(x, tag_cuter)
tokens <- tokens[nchar(tokens)>1]
return(paste(tokens,names(tokens))) # 将词性和词合并在一个栏位中,后面会再分开
})
}
1
2
3
4
5
6
7
8
9
10
11
12
13
# 将全文用标注词性的断词函式断开
tag_tokens <- MetaData %>%
unnest_tokens(word, sentence, token=tag_tokenizer)
str(tag_tokens)

# 将词和词性分割成 2 栏,并新增至 Data Frame 中
new_df <- separate(tag_tokens, word, c("word", "tag"), " ")

# 筛选出所有的名词
new_df_n <- new_df %>%
filter(tag %in% c("n","nr","nr1","nr2","nrj","nrf","ns","nsf","nt","nz","nl","ng"))
# filter(tag == "x")
head(new_df_n)

筛选出的所有名词

1
2
3
4
5
6
7
8
9
10
# 计算每个词出现的次数
tokens_count <- new_df_n %>%
filter(nchar(.$word)>1) %>%
group_by(word) %>%
summarise(sum = n()) %>%
filter(sum>10) %>%
arrange(desc(sum))

# 查看看出现最多的前20个名词
head(tokens_count,20)

查看名词的前20

1
2
3
4
5
6
7
# 画出文字云
tokens_count %>%
filter(word!=c("比特币","价格"))%>%
top_n(20)%>%
wordcloud2()

# “原文”是ptt中出现格式词汇,应该去掉。

文字云