程序设计一:分词和词云
功能一
功能:将数据读入,再使用jieba库对文件中的弹幕内容进行分词处理,并将所有分词存入列表。
使用函数GetText
实现这一功能,代码如下:
def GetText(filepath):
'''
读入文档并分词
:param filepath: 字符串型文件地址,读入格式为csv文件
:return: 列表类型,采用 jieba 分词后的结果
'''
all_words = []
with open(filepath, encoding='utf-8')as f: # 编码方式 utf-8
reader = csv.reader(f)
headers = next(reader) # 读入标题行
Row = namedtuple('Row', headers) # 构建行结构
for each_row in reader:
row = Row(*each_row) # 将每一行数据转换成行结构
row_text = row.content
row_words = jieba.lcut(row_text) # 采用jieba库来分词
all_words.extend(row_words) # 分词结果存入列表
return all_words
功能二
功能:统计词频,读入停用词表,并过滤掉停用词。
使用StatWord
函数实现这一功能,代码如下:
def StatWord(all_words):
'''
统计词频,并过滤停用词
:param all_words: 列表类型,包含分词
:return: 字典类型,值为非停用词的词频
'''
counts = {}
#载入停用词
stopwords = [line.strip() for line in open('stopwords_list.txt', 'r',encoding='utf-8').readlines()]
#统计非停用词的词频
for word in all_words:
if word not in stopwords and word != ' ':
counts[word] = counts.get(word, 0) + 1
return counts
在主函数中调用该函数实现功能运行程序,统计结果如下(部分截图):
功能三
采用WordFiltrate
函数筛选掉低频词,并得到非低频词;
然后采用GetCharacters
函数从非低频词中提取出特征集
def WordFiltrate(counts):
'''
将所有词按照词频排序,并去除低频词
:param counts:字典类型,分词极其词频
:return: 元组列表,词和频率,按照词频从高到低排列
'''
items = list(counts.items()) # 转换为元组列表
items.sort(key = lambda x:x[1],reverse=True) # 按照元组的第二个元素(词频)排序
for i in range(len(items)): # 筛选非低频词
if items[i][1] <= 5:
items = items[:i-1]
break
return items
def GetCharacters(items):
'''
提取特征词
:param items: 元组列表,特征词和词频
:return: 列表,特征词集
'''
characters = []
for item in items:
characters.append(item[0])
return characters
在主函数中采取运行上述函数,实现本题功能,可以得到特征集和相应的词频,该部分结果不在展示(因为只去掉了低频词,所以高频词的结果呈现和上一题相同)。
功能四
采用TextVector
函数分析相应文本,得到该文本中所有句子的特征向量以及所有特征词的词频。其中,每次迭代调用GetVector
函数得到每个句子的特征向量。
def GetVector1(sentence, characters, word_freq):
'''
提取句子的特征向量
:param sentence: 字符,待分析的句子
:param characters: 列表,特征集
:param word_freq: 一维列表,所有特征词的词频
:return: 句子的特征向量
'''
words = jieba.lcut(sentence)
vector = [0] * len(characters)
for i in range(len(characters)):
for word in words:
if word == characters[i]:
vector[i] = 1
word_freq[i] += vector[i]
return vector
def GetVector2(sentence, characters):
'''
提取句子的特征向量
:param sentence: 字符,待分析的句子
:param characters: 列表,特征集
:return: 句子的特征向量
'''
words = jieba.lcut(sentence)
vector = [0] * len(characters)
for i in range(len(characters)):
for word in words:
if word == characters[i]:
vector[i] = 1
return vector
def TextVector(filepath, characters):
'''
读入待分析文本,调用 GetVector 函数统计每个句子的特征向量,并返回待分析文本的相关信息
:param filepath: 待分析文本路径
:param characters: 特征词集
:return: text_vector: 二维列表,存储的是整篇文章所有句子的特征向量
word_freq: 一维列表,所有特征词的词频(每个特征词共在多少个句子中出现)
num_sentence: 整数,总共有多少个句子
'''
text_vector = []
word_freq = [0] * len(characters)
with open(filepath, encoding='utf-8') as f: # 编码方式
reader = csv.reader(f)
headers = next(reader)
Row = namedtuple('Row', headers)
num_sentence = 0
for each_row in reader:
num_sentence += 1
row = Row(*each_row)
row_text = row.content
if len(row_text) > 5:
vector = GetVector1(row_text, characters, word_freq)
text_vector.append([row_text, vector])
return text_vector, word_freq, num_sentence
为方便展示,定义函数来保存结果,代码如下
def WriteTextVector(text_vector):
with open('vectors_save.csv', 'w', encoding='utf-8', newline='') as fp:
writer = csv.writer(fp)
header = ['text', 'vector']
writer.writerow(header) # 设置第一行属性名
writer.writerows(text_vector) # 将数据写入文件
在主函数中调用这些函数实现上述功能,截图如下(部分):
功能五
定义SIMILARITY
类,采用两种方法计算句子之间的相似度
其中,方法Cos_dis
计算余弦相似度,方法Euc_dis
计算欧几里得相似度
class SIMILARITY(object):
def __init__(self, sentence_1, sentence_2, characters):
self.sentence_1 = sentence_1
self.sentence_2 = sentence_2
self.characters = characters
self.vector_1 = GetVector2(self.sentence_1, self.characters)
self.vector_2 = GetVector2(self.sentence_2, self.characters)
def Cos_dis(self):
v1 = np.array(self.vector_1)
v2 = np.array(self.vector_2)
v1_norm = np.linalg.norm(v1)
v2_norm = np.linalg.norm(v2)
self.cos_dis = np.dot(v1, v2) / (v1_norm * v2_norm)
return self.cos_dis
def Euc_dis(self):
self.euc_dis = math.sqrt(sum([(a - b) ** 2 for (a, b) in zip(self.vector_1, self.vector_2)]))
return self.euc_dis
在主函数中,以两条弹幕为例子,分别调用上述两种方法计算距离,代码如下
# 计算距离
sentence_1 = '哈哈哈哈好吃'
sentence_2 = '还不错哈哈哈哈'
dis = SIMILARITY(sentence_1,sentence_2,characters)
cos_dis = dis.Cos_dis()
euc_dis = dis.Euc_dis()
print("cos_dis = {},euc_dis = {}".format(cos_dis,euc_dis))
功能六
使用WordCloud
包绘制词云图,定义WordsCloud
函数实现该功能,函数定义代码如下:
def WordsCloud(items):
'''
绘制词云图
:param items: 元组列表,特征词和词频
:return:
'''
frequency = {} # 词云所用词汇和词频
for i in range(50):
frequency[items[i][0]] = items[i][1]
font = "C:\Windows\Fonts\STXINGKA.TTF" # 字体路径
wc = WordCloud(font_path=font,background_color="white") # 可以增加 mask=mask_image 设置
wc.fit_words(frequency) # 基于前面的词频统计
plt.imshow(wc)
plt.axis("off")
plt.show()
在主函数中调用,结果如下:
功能七
使用 TF-IDF 的方法构建特征词集,在之前第四题中,已经利用函数TextVector
统计了每个词语在多少的句子中出现,并记录了句子的数量。本题定义了TfIdfValue
函数,计算每个词的Tf*Idf值,并依据该值来排序。
def TfIdfValue(items, word_freq, num_sentence):
'''
按照TF-IDF方法,筛选特征词,构造特征词集
:param items: 元组列表,所有词语极其词频
:param word_freq: 一维列表,每个词在多少句子中出现
:param num_sentence: 整数,句子总数量
:return: 字典,按照 Tf*Idf 由大到小排序的特征词和值
'''
# 计算每个词的TF值
word_tf = {} # 存储每个词的tf值
sum_fenq = 0
for item in items:
sum_fenq += int(item[1])
for item in items:
word_tf[item[0]] = item[1] / sum_fenq
# 计算每个词的IDF值
word_idf = {} # 存储每个词的idf值
for i in range(len(items)):
word_idf[items[i][0]] = math.log(num_sentence / (word_freq[i] + 1))
# 计算每个词的TF*IDF的值
word_tf_idf = {} # 存储每个词的 tf*idf 值
for item in items:
word_tf_idf[item[0]] = word_tf[item[0]] * word_idf[item[0]]
# 对字典按值由大到小排序
tf_idf_list = sorted(word_tf_idf.items(), key=operator.itemgetter(1), reverse=True)
return tf_idf_list
在主函数中调用该功能并运行,使用部分样例的结果如下:
和词频统计的方式相对照,排序结果大致相同,个别词略有差异,在前十个高频词中,”蒜“,”加油“等词的排序不太一样。
综合两种方法来看,第二种计算方法更能反映每个分词的重要程度。