三国演义人名统计及可视化

1.人名统计

首先,三国演义.txt需要各位自行下载,然后我们需要导入jieba(结巴)库,在后续完成代码的过程中我们需要使用jieba来帮我们自动分词

然后是对于一些不需要分词的词语我们需要剔除:

        1.单字成词的我们不需要“的”“地”等

        2.还有一些二字词语也不需要“你们”“此外”等

所以我们需要建立一个词语库excludes来剔除这些词汇

excludes = {'却说', '二人', '不可', '主公', '陛下', '汉中', '只见', '众将', '后主', '蜀兵', '上马', '大叫', '太守',
            '此人', '夫人',
            '先主', '后人', '背后', '城中', '天子', '一面', '何不', '大军', '忽报', '先生', '百姓', '何故', '不能',
            '如此', '如何',
            '然后', '先锋', '不如', '赶来', '原来', '令人', '江东', '下马', '喊声', '正是', '徐州', '忽然', '荆州',
            '左右', '军马',
            '因此', '成都', '不见', '未知', '大败', '大事', '之后', '一军', '引军', '起兵', '军中', '接应', '引兵',
            '次日', '大喜',
            '进兵', '大惊', '可以', '以为', '大怒', '不得', '心中', '下文', '一声', '追赶', '粮草', '天下', '东吴',
            '于是', '都督',
            '曹兵', '一齐', '分解', '回报', '分付', '只得', '出马', '三千', '大将', '许都', '随后', '报知', '今日',
            '不敢', '魏兵',
            '前面', '之兵', '且说', '众官', '洛阳', '领兵', '商议', '军士', '星夜', '精兵', '城上', '之计', '不肯',
            '相见', '其言',
            '一日', '而行', '文武', '襄阳', '准备', '若何', '出战', '亲自', '必有', '一人', '人马', '不知', '何人',
            '此事', '之中',
            '伏兵', '祁山', '乘势', '忽见', '大笑', '樊城', '兄弟', '首级', '立于', '西川', '传令', '当先', '五百',
            '一彪', '坚守',
            '此时', '之间', '投降', '五千', '埋伏', '长安', '三路', '遣使', '将军', '关兴', '军师', '朝廷', '三军',
            '大王', '回见',
            '大将军', '必然', '将士', '是夜', '小路'}

完成上述步骤后,我们还要注意一些人名有多个别称,比如“刘备”在文中也会被称为“刘皇叔”“玄德”等,所以我们需要将这些重复计数统一起来,建立一个merges库:

merges = [('刘备', ('玄德', '玄德曰', '玄德问', '刘玄德', '玄德大', '玄德自', '玄德闻', '皇叔', '刘皇叔')),
          ('关羽', ('关公', '云长', '关云长')),
          ('孔明', ('诸葛亮', '孔明曰', '孔明笑', '孔明之', '孔明自')),
          ('曹操', ('丞相', '孟德', '曹公', '曹孟德')),
          ('张飞', ('翼德', '张翼德'))
          ]

然后是代码的主体部分: 

def countWords(excludes, merges):
    txt = open("三国演义.txt", 'r', encoding='utf-8').read() # "三国演义.txt"打不开的话,设置三国演义的绝对路径(记得\\代表复制路径中的\)
    words = jieba.lcut(txt)
    counts = {}
    # 取出长度为一的词和符号以及excludes中的词
    for word in words:
        if len(word) == 1 or word in excludes:
            continue
        else:
            counts[word] = counts.get(word, 0) + 1 # get()的用法:后面的'0'意思是当'word'第一次出现(此时没有键值)则word的键值为1
    # 合并名称相同的人名
    for merge in merges:
        for name in merge[1]:
            counts[merge[0]] += counts.get(name, 0)
            del counts[name]
    word_list = list(counts.items()) # items()将字典转化为列表,每个键值对生成一个元组存入列表中
    word_list.sort(key=lambda x: x[1], reverse=True)
    return word_list

第2行:将三国演义这个文件变成可读性的值赋予变量txt

第3行:通过jieba将三国演义的中的词语进行分词,并将结果赋予变量words

第10行:为字典变量counts加入键word,通过for循环后,键值为word在words中出现的次数,每次加一

第12行:遍历列表merges中的元组并赋值给merge

第13行:遍历元组merge中的元组并赋值给name

第14行:get()获取name所在字典counts中对应的键的键值,并将其加给元组第一个元素所在字典counts中对应的键的键值上

第15行:从列表merges中剔除元素name

第17行:sort()为排序函数,'key'用于比较,'reverse'的结果(True/False)用于升/降序

import jieba


def countWords(excludes, merges):
    txt = open("三国演义.txt", 'r', encoding='utf-8').read()
    words = jieba.lcut(txt)
    counts = {}
    # 取出长度为一的词和符号以及excludes中的词
    for word in words:
        if len(word) == 1 or word in excludes:
            continue
        else:
            counts[word] = counts.get(word, 0) + 1
    # 合并名称相同的人名
    for merge in merges:
        for name in merge[1]:
            counts[merge[0]] += counts.get(name, 0)
            del counts[name]
    word_list = list(counts.items())
    word_list.sort(key=lambda x: x[1], reverse=True)
    return word_list


excludes = {'却说', '二人', '不可', '主公', '陛下', '汉中', '只见', '众将', '后主', '蜀兵', '上马', '大叫', '太守',
            '此人', '夫人',
            '先主', '后人', '背后', '城中', '天子', '一面', '何不', '大军', '忽报', '先生', '百姓', '何故', '不能',
            '如此', '如何',
            '然后', '先锋', '不如', '赶来', '原来', '令人', '江东', '下马', '喊声', '正是', '徐州', '忽然', '荆州',
            '左右', '军马',
            '因此', '成都', '不见', '未知', '大败', '大事', '之后', '一军', '引军', '起兵', '军中', '接应', '引兵',
            '次日', '大喜',
            '进兵', '大惊', '可以', '以为', '大怒', '不得', '心中', '下文', '一声', '追赶', '粮草', '天下', '东吴',
            '于是', '都督',
            '曹兵', '一齐', '分解', '回报', '分付', '只得', '出马', '三千', '大将', '许都', '随后', '报知', '今日',
            '不敢', '魏兵',
            '前面', '之兵', '且说', '众官', '洛阳', '领兵', '商议', '军士', '星夜', '精兵', '城上', '之计', '不肯',
            '相见', '其言',
            '一日', '而行', '文武', '襄阳', '准备', '若何', '出战', '亲自', '必有', '一人', '人马', '不知', '何人',
            '此事', '之中',
            '伏兵', '祁山', '乘势', '忽见', '大笑', '樊城', '兄弟', '首级', '立于', '西川', '传令', '当先', '五百',
            '一彪', '坚守',
            '此时', '之间', '投降', '五千', '埋伏', '长安', '三路', '遣使', '将军', '关兴', '军师', '朝廷', '三军',
            '大王', '回见',
            '大将军', '必然', '将士', '是夜', '小路'}

merges = [('刘备', ('玄德', '玄德曰', '玄德问', '刘玄德', '玄德大', '玄德自', '玄德闻', '皇叔', '刘皇叔')),
          ('关羽', ('关公', '云长', '关云长')),
          ('孔明', ('诸葛亮', '孔明曰', '孔明笑', '孔明之', '孔明自')),
          ('曹操', ('丞相', '孟德', '曹公', '曹孟德')),
          ('张飞', ('翼德', '张翼德'))
          ]

word_list = countWords(excludes, merges)
for i in range(30):
    word, count = word_list[i]
    print('{0:^10}{1:{3}^10}{2:^15}'.format(i + 1, word, count, chr(12288)))

# 倒数第2行:由于之前的操作word_list的形式为[(, ), (, ), (, )],所以在为word和count赋值时也应遵照此形式
# 倒数第1行:将之前的结果print出来用于检查,其中格式问题请自行百度,这里不详细说了

2.可视化结果

我们需要先导入数学图形库

import matplotlib.pyplot as plt

然后设置一个变量(例:fig)让它成为表格的图形参数

但是这时的表为空白表,用add_axes()添加子图像和坐标 # 左(y)下(x)宽(f(x))高(f(y))

之后将列表word_list中每个元组的人名和计数分配到两个列表里

用ber()函数绘制柱形图,并用show()函数表现出来

fig = plt.figure()
ax = fig.add_axes([0, 0, 1, 1])
word_s = []
count_s = []
for i in range(10):
    word, count = word_list[i]
    word_s.append(word)
    count_s.append(count)
ax.bar(word_s, count_s)
plt.show()

 最后将完整的代码放到下面

# 如果在pycharm中你的图像没有文字,就是没有字体适配的问题

# 如果你的结果中“刘备”的数量没有2000就是合并人名出来错误,不建议修改(因为我也没改完),直接用条件语句合并也能达到此效果(或者嵌套函数)

import jieba
import matplotlib.pyplot as plt


def countWords(excludes, merges):
    txt = open("三国演义.txt", 'r', encoding='utf-8').read()
    words = jieba.lcut(txt)
    counts = {}
    # 取出长度为一的词和符号以及excludes中的词
    for word in words:
        if len(word) == 1 or word in excludes:
            continue
        else:
            counts[word] = counts.get(word, 0) + 1
    # 合并名称相同的人名
    for merge in merges:
        for name in merge[1]:
            counts[merge[0]] += counts.get(name, 0)
            del counts[name]
    word_list = list(counts.items())
    word_list.sort(key=lambda x: x[1], reverse=True)
    return word_list


excludes = {'却说', '二人', '不可', '主公', '陛下', '汉中', '只见', '众将', '后主', '蜀兵', '上马', '大叫', '太守',
            '此人', '夫人',
            '先主', '后人', '背后', '城中', '天子', '一面', '何不', '大军', '忽报', '先生', '百姓', '何故', '不能',
            '如此', '如何',
            '然后', '先锋', '不如', '赶来', '原来', '令人', '江东', '下马', '喊声', '正是', '徐州', '忽然', '荆州',
            '左右', '军马',
            '因此', '成都', '不见', '未知', '大败', '大事', '之后', '一军', '引军', '起兵', '军中', '接应', '引兵',
            '次日', '大喜',
            '进兵', '大惊', '可以', '以为', '大怒', '不得', '心中', '下文', '一声', '追赶', '粮草', '天下', '东吴',
            '于是', '都督',
            '曹兵', '一齐', '分解', '回报', '分付', '只得', '出马', '三千', '大将', '许都', '随后', '报知', '今日',
            '不敢', '魏兵',
            '前面', '之兵', '且说', '众官', '洛阳', '领兵', '商议', '军士', '星夜', '精兵', '城上', '之计', '不肯',
            '相见', '其言',
            '一日', '而行', '文武', '襄阳', '准备', '若何', '出战', '亲自', '必有', '一人', '人马', '不知', '何人',
            '此事', '之中',
            '伏兵', '祁山', '乘势', '忽见', '大笑', '樊城', '兄弟', '首级', '立于', '西川', '传令', '当先', '五百',
            '一彪', '坚守',
            '此时', '之间', '投降', '五千', '埋伏', '长安', '三路', '遣使', '将军', '关兴', '军师', '朝廷', '三军',
            '大王', '回见',
            '大将军', '必然', '将士', '是夜', '小路'}

merges = [('刘备', ('玄德', '玄德曰', '玄德问', '刘玄德', '玄德大', '玄德自', '玄德闻', '皇叔', '刘皇叔')),
          ('关羽', ('关公', '云长', '关云长')),
          ('孔明', ('诸葛亮', '孔明曰', '孔明笑', '孔明之', '孔明自')),
          ('曹操', ('丞相', '孟德', '曹公', '曹孟德')),
          ('张飞', ('翼德', '张翼德'))
          ]

word_list = countWords(excludes, merges)
for i in range(30):
    word, count = word_list[i]
    print('{0:^10}{1:{3}^10}{2:^15}'.format(i + 1, word, count, chr(12288)))

fig = plt.figure()
ax = fig.add_axes([0, 0, 1, 1])
word_s = []
count_s = []
for i in range(10):
    word, count = word_list[i]
    word_s.append(word)
    count_s.append(count)
ax.bar(word_s, count_s)
plt.show()

你可能感兴趣的:(生鸡蛋23大计の题,python,算法)