IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> 词频统计(标准版) -> 正文阅读

[Python知识库]词频统计(标准版)

之前写的词频统计有点low(【自然语言处理】最简单的词频统计),给许老师看了以后提了许多改进意见,这里记录一下。

1 原代码

import operator
import string


# 读文件
contents = []   # 存放txt文件每行的内容
path = r"C:\Users\Lenovo\Desktop\corpus.tc.en"
with open(path, encoding='gb18030', errors='ignore') as f:
    for line in f.readlines():
        line.encode('latin-1', 'ignore')        # ignore it
        contents.append(line)
# f.close()

# 词频统计
dic = {}
t = []
for line in contents:           # 每一行
    for i in line:              # 去标点, string.punctuation:返回所有标点集
        if i in string.punctuation:
            line = line.replace(i, " ")
    t = line.lower().split()    # 转小写,并根据空格分词
    for word in t:              # 每个词
        if word not in dic:
            dic[word] = 1
        else:
            dic[word] = dic[word] + 1

res = sorted(dic.items(), key=operator.itemgetter(1), reverse=True)     # 排序的结果是list类型, list里面是tuple


# 写入结果
path2 = r'C:\Users\Lenovo\Desktop\result.txt'
file = open(path2, 'w', encoding='utf-8')       # --> with open
for item in res:
    file.write(item[0] + " ")   # "%s %d" % item
    file.write(str(item[1]))
    file.write("\n")

print("写入完成")

2 存在的问题

2.1 内存

我的思路是将该文件全部存到内存contents中,然后再从内存中一行一行取。当文件很大时很容易爆内存,因此最好的解决方式是读一行处理一行
----------------------------20220323补充:--------------------------------------
这个真的是很重要的一点,不要想着一下先读内存再处理,这真不中。

2.2 with open

打开文件最好选择用类似with open() as f的方式,而不是file = open()。因为前者更安全。
补充一点,用前者不需要加f.close(),但后者需要加。

2.3 标点符号

NLP中标点符号不要去掉,这也算在tokens里。

2.4 小写问题

不用转小写,因为很多专有名词(比如Apple)和转小写之后的意思(比如apple)截然不同。

2.5 get方法

get方法是python字典的方法,使用方式:

dict.get(key[, value])

value可选,当key不存在时,返回指定的value值(充当设定默认值的作用)。

因此,下面这段代码:

if word not in dic:
	dic[word] = 1
else:
	dic[word] = dic[word] + 1

可以精简为:

dic[word] = dic.get(word, 0) + 1

2.6 字符串拼接

for item in res:
    file.write(item[0] + " ")   # "%s %d" % item
    file.write(str(item[1]))
    file.write("\n")

上面的代码中,python中字符串拼接的+号速度是很慢的。建议用类似的C语言的形式去输出:(具体语法暂时没查到,但是tuple类型确实可以这么用)

for item in res:
	file.write("%s %d\n" % item)

2.7 编码

一会儿用国标码gb一会儿用utf-8太乱了,国际上一般使用的就是utf-8

2.8 接口与传参

建议处理成一个可以直接调用的函数接口,以后直接传入文件就可以得到结果。

if __name__ == "__main__":
	/*
	*/

假设我们有了handle()save()函数,那我们可以这样写main函数:

if __name__ == "__main__":
    print(sys.argv)
    save(sys.argv[2], handle(sys.argv[1]))

关于这个部分不理解的可以参考下面两篇文章:
如何简单地理解Python中的if __ name __ == ‘__ main __’
Python中 sys.argv[]的用法简明解释

2.9 关于rrbwwb

这一点老师并没有指出来,可能不是大问题。但老师给的代码里还是用到了rbwb。查阅资料后发现这两个打开文件的方式适合于处理二进制文件。
更多参考:[Python] 详细解答 open 函数中 r 和 rb 的区别

2.10 tqdm(非必要)

当文件较大时,我们可以给处理过程加入进度条。
比如运行如下代码:

from time import sleep
from tqdm import tqdm
for i in tqdm(range(1000)):
    sleep(0.01)

就可以得到这样的结果:(脑部进度条.gif)
在这里插入图片描述
如果涉及对某个数组的循环可以这样:

pbar = tqdm(["a", "b", "c", "d"])
for char in pbar:
    sleep(1)
    pbar.set_description("Processing %s" % char)

我们把需要执行循环的数组用tqdm()一下,就可以显示出进度条了。
(可恶,我被上面这些操作误导了)
正确的思路可以参考我的另一篇文章:tqdm显示逐行读取文件并处理

3 修改代码

在修改了上面的问题后,词频统计的代码修改如下:

# encoding: utf-8
import sys
from tqdm import tqdm

# "abc cd" -> ["abc", "", "cd"]


def handle(srcf):
    vocab = {}
    count = 0
    with open(srcf, "rb") as frd:
        for line in frd:
            count = count + 1
    pbar = tqdm(total=count)

    with open(srcf, "rb") as frd:
        for line in frd:
            tmp = line.strip()  # "\r\n"
            if tmp:
                tmp = tmp.decode("utf-8")
                for word in tmp.split():
                    if word:
                        vocab[word] = vocab.get(word, 0) + 1
            pbar.update(1)
    pbar.close()
    return vocab


def save(fname, obj):
    with open(fname, "wb") as fwrt:
        fwrt.write(repr(obj).encode("utf-8"))


def load(fname):
    with open(fname, "rb") as frd:
        tmp = frd.read().strip()
        rs = eval(tmp.decode("utf-8"))
        return rs


if __name__ == "__main__":
    print(sys.argv)
    save(sys.argv[2], handle(sys.argv[1]))

这个代码在编辑器上是跑不通的,需要使用cmd,第一个参数是要处理的文件地址,第二个参数是保存的文件地址。我的使用截图如下:
在这里插入图片描述

4 补充

补充一下和老师的讨论记录,稍做记录:
在这里插入图片描述
在这里插入图片描述

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2022-03-24 00:30:34  更:2022-03-24 00:31:52 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 21:01:48-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码