使用python正则表达式计算文档中单词的频率

时间:2011-03-23 12:56:08

标签: python regex dictionary count frequency

创建一个python模块,该模块读取文件,删除停用词并输出带有单词及其频率的python字典(文档中出现的次数)。

def run():
filelist = os.listdir(path)
regex = re.compile(r'.*<div class="body">(.*?)</div>.*', re.DOTALL | re.IGNORECASE)
reg1 = re.compile(r'<\/?[ap][^>]*>', re.DOTALL | re.IGNORECASE)
quotereg = re.compile(r'&quot;', re.DOTALL | re.IGNORECASE)
puncreg = re.compile(r'[^\w]', re.DOTALL | re.IGNORECASE)
f = open(stopwordfile, 'r')
stopwords = f.read().lower().split()
totalfreq = {}

filewords = {}
htmlfiles = []
for file in filelist:
    if file[-5:] == '.html':
        htmlfiles.append(file)

for file in htmlfiles:
    f = open(path + file, 'r')
    words = f.read().lower()
    words = regex.findall(words)[0]
    words = quotereg.sub(' ', words)
    words = reg1.sub(' ', words)
    words = puncreg.sub(' ', words)
    words = words.strip().split()

    for w in stopwords:
        while w in words:
            words.remove(w)

     freq = {}
    for w in words:
       if w in freq:
           totalfreq[w] = totalfreq[w] + 1
           freq[w] = freq[w] + 1
       else:
           totalfreq[w] = 1
           freq[w] = 1
           filewords[file] = freq


    print totalfreq

这将打印该文件中的所有“不间断”字样及其在文件中出现的频率:输出如下:

  

{{'星期六':1,'爱尔兰':1,'家庭':1,'给':1,'年':2,'周末':1,'史蒂夫':1,'来宾' :1,'问题':1,'在':2,'努力':1,'伙伴':1,'灭绝':1,'礼服':1,'儿童':4,'utans':1 ,'27':1,'加注':1,'衣柜':1,'发型':2,'制造':1,'humphreys':1,'亲戚':1,'动物园':5,'濒危':1,'星期日':1,'特殊':1,'回答':1,'公开':1,'意识':1,'计划':1,'活动':1,'rhiona' :1,'猩猩':4,'计划':1,'leonie':1,'orang':1,'昨天':2,'免费':2,'手':1,'野':1 ,'独立':1,'部分':1,'准备':1,'透露':1,'天':1,'男人':1,'图片':1,'基恩':1,'动物':1,'14':1,'kevin':1,'16':1,'32':1,'年龄':1,'sibu':1,'dublin':2,'keepers' :1,'face':1,'mujur':1,'red':2,'orangutan':1,'species':1,'entry':1,'努力':1,'显示':1 ,'上午11点':1,'涌入':1,'3pm':1}

     

{'最新':1,'出生':2,'orang':1,'月':1,'史蒂夫':1,'问题':1,'utans':1,'孩子': 4,'工作人员':1,'风头':1,'27':1,'基于':1,'关注':1,'星期日':1,'3pm':1,'最后':1, '4':1,'maeve':1,'意识':1,'给':1,'活动':1,'长颈鹿':1,'脸书':1,'准备':1,'背景':1,'养育':1,'天':1,'登场':1,'rothschild':1,'repers':1,'电子邮件':1,'步骤':1,'11am': 1,'page':1,'picture':1,'born':1,'result':1,'year':2,'saturday':1,'special':1,'closet':1, '头发':2,'部分':1,'bennet':2,'妈妈':3,'mujur':1,'条件':1,'公共':1,'红色':2,'显示':1,'猩猩':4,'自由':2,'守门人':1,'11月':1,'关心':1,'发送':1,'伟大':1,'起源': 1,'32':1,'邀请':1,'都灵':2,'计划':1,'猩猩':1,'努力':1,'涌入':1,'命名':1, '家庭':1,'高兴':1,'天气':1,'客人':1,'灭绝':1,'发布':1,'留下深刻印象':1,'加注':1,'透露':1,'剩下的''1,'humphreys':1,'自信':1,'小腿':3,'入口':1,'shane':1,'part':1,'helen':1,'注意' :1,'努力':1,'案例':1,'制作':2,'动物':1,'14':1,'16':1,'ms':1,'野':1 ,'savanna':1,'爱尔兰':1,'给':1,'居民':1,'建议':1,'滑':1,'在':2,'伙伴':1,'打扮':1,'种类':1,'kevin':1,'rhiona':1,'make':1,'zoo':3,'濒临灭绝':1,'亲戚':1,'回答' :1,'差':1,'独立':1,'计划':1,'leonie':1,'时间':1,'昨':1,'手':1,'hickey':1 ,'周末':1,'男':1,'sibu':1,'年龄':1,'稳定':2,'面子':1,'禁闭':1,'非洲':2,'条目':1,'keane':1,'clarke':2,'left':1}

但我需要将两个总数从两个文件或大量文件中加在一起,以便在所有文件中给出单词的总计数,例如“zoo”。第1档动物园= 5第2档动物园= 3总计= 8。

我似乎无法弄清楚我如何计算多个文件的单词,而不是一次只计算一个。

有什么想法吗?!

4 个答案:

答案 0 :(得分:2)

fileinput模块可让您轻松处理多个文件。

答案 1 :(得分:2)

'<\/?[ap][^>]*>'中的反斜杠无用,因为'/'不是特殊字符

'[^\w]' '\W'顺便提一句'[^\w]+''[^\w]'更有效

re.DOTALL r'<\/?[ap][^>]*>'没用,因为此RE中没有点

如果您words = f.read().lower()降低字母数,则不需要 re.IGNORECASE

替换的RE可以放在一个RE:reg123 = re.compile(r'(</?[ap][^>]*>|&quot;|\W+)')

文件不是文件名的好名称,它会覆盖现有内置函数的名称

用生成器表达式替换代码行以获得 htmfiles 更好

我不明白为什么words = regex.findall(words)[0]

中的'[0]'

您还可以将用于替换的RE中的停用词分为' '

stopwords = '|'.join(f.read().lower().split())

将被包含在RE中以进行替换

filewords[file] = freq的缩进很糟糕

我建议你进行以下改进;我没有测试它,因为我不是要处理的文件。这当然不是完美的。要求不清楚点。

def run():

    from collection import difaultdict

    with open(stopwordfile, 'r') as f:
        stopwords = '|'.join(f.read().lower().split())

    regex = re.compile(r'.*<div class="body">(.*?)</div>.*', re.DOTALL)
    reg123 = re.compile(r'(</?[ap][^>]*>|&quot;|\W+|'+stopwords+')')

    totalfreq = defaultdict(int)
    filewords = {}

    for filename in (fn for fn in os.listdir(path) if fn[-5:] == '.html'):
        with open(path + filename, 'r') as f:
            ch = regex.findall(f.read().lower())[0]
            ch = reg123.sub(' ', ch)
            words = ch.strip().split()

        freq = defaultdict(int)
        for w in words:
            totalfreq[w] += 1
            freq[w] += 1
        filewords[filename] = freq

    print totalfreq

我不太清楚你的问题。请给出精确度

答案 2 :(得分:0)

可能的解决方案是

result = {}
for d in dictionaries:
  for k,v in d.iteritems():
    result[k] = result.get(k,0) + v

for k,v in result.iteritems():
  print('total occurences of {0}: {1}'.format(k,v))

...其中dictionaries只是每个输入文件的单词到频率映射列表。

答案 3 :(得分:0)

假设files是您拥有的每个文件的频率列表,请尝试以下操作:

from itertools import groupby, chain
total = dict(
              (key, sum(c[1] for c in vals))
              for key, vals in 
              groupby(
                  sorted(
                      chain(
                          *(f.items() for f in files)
                      )
                  ), 
                  lambda x: x[0]
              )
            )