如何用Python计算段落中英文单词的百分比
假设我有一段包含不同语言的文字,比如:
这是一段英文。 这是在英国段。 Это пункт на английском языке. این بند در زبان انگلیسی است.
我想计算这段文字中有多少百分比是英文单词。所以我想问一下,怎么用Python来实现这个计算。
5 个回答
一个很有用的数据结构可以帮助我们做这种事情,那就是字典树(trie)。
如果我们使用我修改过的英文单词列表,来自另一篇帖子:
import os
import json
import urllib3
eng_trie = {}
def add_to_trie(trie: dict, word: str, lower: bool=False) -> dict:
if lower:
word = word.lower()
letter = word[:1]
if len(word) == 1:
# This is the last letter, add a terminator
trie[word] = {**trie.get(word, {}), "EOW": True}
else:
if not trie.get(letter):
trie[letter] = {}
trie[letter] = add_to_trie(trie[letter], word[1:])
return trie
if __name__ == "__main__":
output_file = "./data/words.json"
url = "https://github.com/JonathanRys/data-repository/blob/master/data/words.txt?raw=true"
response = urllib3.request("GET", url)
if response.status:
for word in [word.strip() for word in response.data.decode().split('\n')]:
if word:
try:
add_to_trie(eng_trie, word, lower=True)
except Exception as e:
print(f'ERROR for word "{word}": {e}')
with open(output_file, 'w') as f:
print(json.dumps(eng_trie), file=f)
那么使用它的方法是
import json
json_trie = './data/words.json'
def get_data(file: str) -> dict:
with open(file) as f:
trie = json.loads(f.read())
return trie
def check(word: str, trie: dict=get_data(json_trie)) -> bool:
if len(word) == 1:
if trie.get(word):
if trie.get(word).get('EOW'):
return True
else:
return False
if trie:
next_trie = trie.get(word[:1])
if next_trie:
return check(word[1:], next_trie)
return False
def is_english(word: str) -> bool:
if not word:
return False
return check(word)
if __name__ == "__main__":
words = ['albatross', 'run', 'winner', 'success', 'erwrtwaf', 'albat']
for word in words:
if is_english(word):
print(f'English: {word}')
else:
print(f'Not English: {word}')
如果你所有用拉丁字母写的词都是英语的话,你可以使用正则表达式。
首先,你需要获取一份英文单词的列表。然后,逐行读取文件并进行计数!
import string
import urllib2
punctuation = set(string.punctuation)
eng_words_url = 'https://raw.github.com/eneko/data-repository/master/data/words.txt'
eng_words = urllib2.urlopen(eng_words_url).readlines()
eng_words = [w.strip().lower() for w in eng_words]
def remove_punc(str):
return ''.join(c for c in str if c not in punctuation)
total_count = 0
eng_count = 0
with open('filename.txt') as f:
for line in f:
words = remove_punc(line).lower().split()
total_count += len(words)
eng_count += sum(1 for word in words if word.lower() in eng_words)
print '%s English words found' % eng_count
print '%s total words found' % total_count
percentage_eng = 0 if total_count == 0 else (float(eng_count) / total_count * 100)
print '%s%% of words were English' % percentage_eng
比如,这段文字就是你的示例文本:
这是一个英文段落。 这是在英国段。Это пункт на английском языке. این بند در زبان انگلیسی است.
当我在这段文字上运行上面的代码时,输出结果是这样的:
找到5个英文单词
总共找到16个单词
英文单词占总单词的31.25%
正如评论中提到的,由于中文单词之间没有空格,所以这个百分比是不正确的。实际上总共有22个单词,所以正确的百分比应该是22.7%。
有些人发现这个段落里有16个单词。但真的是这样吗?其中一个问题是,如果你想把英语单词的数量和句子里的单词数量进行比较,仅仅用英语的方法是比较困难的。找出英语单词的数量相对简单,但第二部分,也就是找出句子里的总单词数就难多了,因为你需要一些工具来搞清楚“这是在英国段”里到底有多少个单词,这样才能算出英语单词在段落中的比例。
可以试试使用自然语言工具包(NLTK)。NLTK是一个Python库(正在开发与Python3.0的兼容性),里面有你需要的功能,比如计算单词出现的频率、将字符串分割成单词等。此外,它还提供了英语语料库,你可以用来对比句子里的单词,看看哪些是英语单词。
与之配套的书籍《用Python进行自然语言处理》(Natural Language Processing with Python),适用于Python 2.x的第一版,可以在NLTK网站上免费获取。这本书是NLTK库和Python编程的入门书。Wordlist Corpus或Roget's Thesaurus Corpus可能会对你有帮助。另外,还有一个工具可以检测文本的语言。对于混合语言的情况,不太确定这个工具会怎么工作。
这个离线解决方案使用了pyenchant拼写检查模块:
# -*- coding: utf-8 -*
import enchant
dictionary = enchant.Dict("en_US")
paragraph = u"This is paragraph in English. 这是在英国段。Это пункт на английском языке. این بند در زبان انگلیسی است."
words = paragraph.split(" ")
en_count = 0.0
for word in words:
if dictionary.check(word.strip()):
en_count += 1
percent = en_count/len(words) if len(words) != 0 else 0
print str(percent) + "% english words"
输出结果:
31.25% english words