博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
对英文文档中的单词与词组进行频率统计
阅读量:6940 次
发布时间:2019-06-27

本文共 5798 字,大约阅读时间需要 19 分钟。

一、程序分析

 

1、以只读模式读取文件到字符串

def process_file(path):    try:        with open(path, 'r') as file:            text = file.read()    except IOError:        print("Read File Error!")        return None    return text

 

2、对字符串进行数据清洗,返回一个字典

import reword_list = re.sub('[^a-zA-Z0-9n]', ' ', textString).lower().split()

使用正则表达式过滤掉文档中的特殊字符,把它们全部替换为空格,方便后续的分隔操作。(忽略大小写,所以全部使用小写字母)

  

  2.1、只考虑单词频率统计

for word in word_list:     if word in word_freq:          word_freq[word] += 1      else:           word_freq[word] = 1

  判断单词列表中的单词是否在单词频率字典中。

  如果这个单词在字典中,则该单词的个数加1;

  如果这个单词不在字典中,则以这个单词为键,赋值为1,表示这个单词第一次出现。

 

  2.2、考虑单词和词组的频率

    2.2.1、数据结构

    词组是由单词连接构成的,一个单词既可以与前面的单词构成词组,也可以与后面的单词构成词组。

    同时,一个单词可能在文章中多次出现,并且和前后的单词构成多种不同的词组。

    这也就表示几乎每一个单词可以一前一后发散出去,这与图状结构颇为类似。(适用于两个单词构成的词组)

    选择图状结构与当前的问题颇为契合。但是,目前python没有一种已知的图类来供我们操作。(自定义类暂不作考虑) 

    于是我想到了树状结构(两个以上单词构成的词组也适用),砍去了单词向前的发散,只保留向后的。至此,问题就变成了构建森林。

    而在python中,森林是比较容易表示的。用一个字典放置每一棵树的根节点,字典套字典,就形成了森林。

    可能你们要问单词和词组的统计个数放在哪。我使用“Value”作键,键值number这样一种结构放在该单词的字典中。

    具体的字典示例样本参见

 

    2.2.2、具体流程

  

    以索引停在50,词组限制单词个数为3为例:

    (1)在树的根节点中寻找mother节点,找不到就创建mother节点。

"mother":{                    "Value":1                }

    (2)在树的根节点中寻找your节点,找到了继续寻找mother节点,找不到就创建mother节点。(不可能找不到,因为索引经过49之后肯定存在your根节点)

    (3)以此类推,在树的根节点中寻找did节点,找到了继续寻找your节点,,找到了继续寻找mother节点,找不到就创建mother节点......

 

    具体实现:

count = len(word_list) i = 0 while i < count:  # 因为需要用到索引遍历列表,只能使用while来遍历列表     finish = i     start = i - num + 1  # num表示词组的单词个数限制,start表示以该单词作为词组结尾的第一个单词的索引     if start < 0:         start = 0  # 处理开始时索引前面没有单词的特殊情况     index = i     while index >= start:  # 做num次建立节点         if word_list[i] in get_dict_value(word_freq, word_list[index: finish]).keys():             get_dict_value(word_freq, word_list[index: finish])[word_list[i]]['Value'] += 1         else:             get_dict_value(word_freq, word_list[index: finish]).update({word_list[i]: {'Value': 1}})         index -= 1     i += 1
    get_dict_value函数
def get_dict_value(word_freq={}, keys=[]):    """如果keys为字符串,返回word_freq字典中以keys为键的值。    如果keys为列表,则使用eval()函数进行字符串拼接,深度查找word_freq字典中以keys为键的值。"""    if type(keys).__name__ == 'str':        return word_freq[keys]    else:        count = len(keys)        if count == 0:            return word_freq        elif count == 1:            return word_freq[keys[0]]        elif count == 2:            return word_freq[keys[0]][keys[1]]        elif count == 3:            return word_freq[keys[0]][keys[1]][keys[2]] #对寻找三个单词以下的词组进行特化        else:            string = "word_freq['"            string += "']['".join(keys)            string += "']"            return eval(string) #动态寻找字典的值的一般版本

    2.2.3、字典格式化

    数据已经存储到了森林中,接下来就是如何把森林格式化成普通的字典。

    相比深度优先遍历,我选择的是更易理解与实现的广度优先遍历。

    广度优先遍历的原理我不再赘述。

def format_dict(word_freq={}):    """对统计短语的情况生成的复杂字典进行格式化,格式化后的形式为
""" formated_word_freq = {} phrases = [] for word in word_freq.keys(): #将所有根节点放入队列中 phrases.append(word) while len(phrases) > 0: #只要队列还有元素,就表明还没有遍历结束 phrase = phrases[0] if len(get_dict_value(word_freq, phrase)) == 1 and type(phrase).__name__ == 'list': formated_word_freq[' '.join(phrase)] = get_dict_value(word_freq, phrase)['Value'] #搜索到叶子节点了,这个节点存入格式化好的字典中 else: for next_word in get_dict_value(word_freq, phrase): #除"Value"键值对以外的键都入队 temp = [] if type(phrase).__name__ == 'str': temp.append(phrase) else: temp.extend(phrase) if next_word != 'Value': temp.append(next_word) phrases.append(temp) phrases.pop(0) #搜索完队列的第一个节点的子节点,这个节点出队 # print(formated_word_freq) return formated_word_freq

 

3、输出字典(没有改动)

def output_result(word_freq):    if word_freq:        sorted_word_freq = sorted(word_freq.items(), key=lambda v: v[1], reverse=True)        for item in sorted_word_freq[:10]:            print(item)

 

4、主函数

if __name__ == "__main__":    import argparse    parser = argparse.ArgumentParser()    parser.add_argument('path') #路径    parser.add_argument('num') #词组单词个数    args = parser.parse_args()    path = args.path    num = int(args.num)    buffer = process_file(path)    if buffer:        word_freq = process_buffer(buffer, num)        if num != 1:            word_freq = format_dict(word_freq)        output_result(word_freq)

命令行接受两个参数,一个是英文文档的路径,还有一个是构成一个词组的最大单词个数(为1时即单词统计)。没有这个限制,森林里就会出现一棵从第一个单词到最后一个单词的树。

 

二、代码风格说明

  基本遵从PEP8,PEP8 涵盖了诸如空格、函数/类/方法之间的换行、import、对已弃用功能的警告之类的寻常东西,是一个不错的准则。

def get_dict_value(word_freq={}, keys=[]):    """如果keys为字符串,返回word_freq字典中以keys为键的值。    如果keys为列表,则使用eval()函数进行字符串拼接,深度查找word_freq字典中以keys为键的值。"""    if type(keys).__name__ == 'str':        return word_freq[keys]    else:        count = len(keys)        if count == 0:            return word_freq        elif count == 1:            return word_freq[keys[0]]        elif count == 2:            return word_freq[keys[0]][keys[1]]        elif count == 3:            return word_freq[keys[0]][keys[1]][keys[2]] #对寻找三个单词以下的词组进行特化        else:            string = "word_freq['"            string += "']['".join(keys)            string += "']"            return eval(string) #动态寻找字典的值的一般版本

    注释基本也只在关键地方才有,不必面面俱到。

 

三、程序运行命令、运行结果截图 

    运行命令:

python statistic.py Gone_with_the_wind.txt 1
python statistic.py Gone_with_the_wind.txt 2

 

四、简单性能分析 

  运行命令:

python -m cProfile -o result.out -s cumulative statistic.py Gone_with_the_wind.txt 2
python gprof2dot.py -f pstats result.out | dot -Tpng -o result.png

 

  单词统计性能分析:

  词组统计性能分析:

  在进行单词统计时,时间有五成花费在过滤特殊字符上,有三成花费在创建字典上。

  而在词组统计中,过滤特殊字符只占了一成,两层时间在创建森林,六成时间在格式化森林。其中,尤其以list的pop()函数占用时间最多,将近一半的时间用来出队。

  

  程序优化:尝试在不pop()得情况下修改广度优先遍历。尝试另一种数据结构,森林比图占的内存多。

  修改中...

转载于:https://www.cnblogs.com/SuccessfullyReleased/p/9745258.html

你可能感兴趣的文章
ip v5
查看>>
SQL高级查询技巧
查看>>
jar not loaded. org.apache.jasper.JasperExcep
查看>>
ls命令详解
查看>>
【Oracle】数据库启动阶段参数文件、控制文件的问题处理
查看>>
使用Metasploit工作区
查看>>
6425C-Lab13 管理站点与AD复制
查看>>
[转载]中国648个超级亿万富豪都是谁?
查看>>
快捷键
查看>>
mac系统快捷键大全详细介绍
查看>>
shell列变行
查看>>
IOS学习笔记(七)之UISegmentedControl分段控件的基本概念和使用方法
查看>>
结构体指定初始化和位初始化
查看>>
提高性能,MySQL 读写分离环境搭建(二)
查看>>
忘记mysql密码操作
查看>>
Android 动画效果学习笔记
查看>>
Task案例1-处理多个任务
查看>>
shell(3)应用
查看>>
Vue2.0 新手入门 — 从环境搭建到发布
查看>>
赛门铁克发现新的APT组织Gallmaker,目标锁定全球政府、军事和国防机构
查看>>