【问题标题】:Counting frequency of words in documents using python regex使用python regex计算文档中单词的频率
【发布时间】:2011-07-21 07:18:38
【问题描述】:

创建了一个 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

这将打印该文件中的所有“不间断”单词以及它们在文件中出现的频率:输出如下所示:

{{'saturday': 1, 'irish': 1, 'family': 1, 'give': 1, 'year': 2, 'weekend': 1, 'steve': 1, 'guests' : 1,“问题”:1,“在”:2,“努力”:1,“伙伴”:1,“灭绝”:1,“衣服”:1,“孩子”:4,“utans”:1 , '27': 1, 'raise': 1, 'closet': 1, 'haired': 2, 'make': 1, 'humphreys': 1, '亲戚': 1, '动物园': 5, '濒危”:1,“星期日”:1,“特殊”:1,“答案”:1,“公众”:1,“意识”:1,“计划”:1,“活动”:1,“犀牛” : 1, 'orangutans': 4, 'plans': 1, 'leonie': 1, 'orang': 1, 'yesterday': 2, 'free': 2, 'hand': 1, 'wild': 1 , '独立': 1, 'part': 1, 'preparing': 1, 'revealed': 1, 'day': 1, 'man': 1, 'picture': 1, 'keane': 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, 'efforts': 1, 'shows': 1 ,“上午 11 点”:1,“涌入”:1,“下午 3 点”:1}

{'newest': 1, 'birth': 2, 'orang': 1, 'month': 1, 'steve': 1, 'questions': 1, 'utans': 1, 'children': 4、“员工”:1、“聚光灯”:1、“27”:1、“基于”:1、“关注”:1、“周日”:1、“下午3点”:1、“终于”:1、 '4': 1, 'maeve': 1, 'awareness': 1, 'gave': 1, 'activities': 1, 'giraffe': 1, 'facebook': 1, 'preparing': 1, 'background ': 1, '培育': 1, 'day': 1, 'debut': 1, 'rothschild': 1, 'keepers': 1, 'email': 1, 'steps': 1, '11am': 1,'page':1,'picture':1,'born':1,'result':1,'year':2,'saturday':1,'special':1,'closet':1, 'haired': 2, 'section': 1, 'bennet': 2, 'mum': 3, 'mujur': 1, 'conditions': 1, 'public': 1, 'red': 2, 'shows ': 1, 'orangutans': 4, 'free': 2, 'keeper': 1, 'november': 1, 'care': 1, 'sending': 1, 'great': 1, 'origins': 1,“32”:1,“受邀”:1,“都柏林”:2,“计划”:1,“猩猩”:1,“努力”:1,“涌入”:1,“命名”:1, “家庭”:1,“高兴”:1,“天气”:1,“客人”:1,“灭绝”:1,“帖子”:1,“印象”:1,“提高”:1,“透露” ': 1, '雷玛ined':1,'humphreys':1,'自信':1,'小牛':3,'入口':1,'shane':1,'part':1,'helen':1,'细心' :1,“努力”:1,“案例”:1,“制造”:2,“动物”:1,“14”:1,“16”:1,“毫秒”:1,“野生”:1 , 'savanna': 1, 'irish': 1, 'give': 1, 'resident': 1, 'suggestions': 1, 'slip': 1, 'in': 2, 'partner': 1, '连衣裙':1,'物种':1,'kevin':1,'rhiona':1,'make':1,'动物园':3,'濒危':1,'亲戚':1,'答案' : 1,“可怜”:1,“独立”:1,“计划”:1,“leonie”:1,“时间”:1,“昨天”:1,“手”:1,“吻痕”:1 , '周末': 1, '男人': 1, 'sibu': 1, '年龄': 1, '稳重': 2, '脸': 1, '坐月子': 1, '非洲人': 2, '条目':1,'基恩':1,'克拉克':2,'左':1}

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

我似乎无法计算出我如何计算多个文件的字数,而不是一次只计算一个。

有什么想法吗?!

【问题讨论】:

    标签: python regex dictionary count frequency


    【解决方案1】:

    '&lt;\/?[ap][^&gt;]*&gt;' 中的反斜杠没有用,因为'/' 不是特殊字符

    '[^\w]''\W' 顺便说一句,'[^\w]+' 比一个'[^\w]' 更有效

    re.DOTALLr'&lt;\/?[ap][^&gt;]*&gt;' 无用,因为此 RE 中没有点

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

    用于替换的 RE 可以放在一个 RE 中:reg123 = re.compile(r'(&lt;/?[ap][^&gt;]*&gt;|&amp;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
    

    我不太明白你的问题。请给出精度

    【讨论】:

    • 感谢您改进的解决方案,您能解释一下 defaultdict 是什么或它来自哪里吗?它只是在字典中保存当前的不间断单词吗!?谢谢
    • @jenniem001 defaultdictdict 类型的子类,从模块 collections 导入。 d = defaultdict(int) 创建一个字典 d,其行为与普通字典相同,此外还有以下行为:当 k 还不是 d 的键时,在表达式中使用d[k] 会触发在任何后续执行之前在字典d 中创建项目k:0。如果 d 被定义为 defaultdict(list) ,则创建的项目是 k:[ ] ,等等。使用 defaultdict 可以减少代码中的行数,使其更具可读性
    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      一个可能的解决方案是

      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 只是每个输入文件的词频映射列表。

      【讨论】:

      • 什么是词频图?你能解释一下你的答案吗?我对程序的这一部分有点困惑。谢谢
      • 通过词频映射,我指的是您在上面发布的字典,即将一个词映射到文件中出现的次数。我上面的代码合并了所有单个文件的数据。
      【解决方案4】:

      假设 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]
                    )
                  )
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-01-07
        • 2014-05-18
        • 1970-01-01
        • 2020-04-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多