2011-03-23 75 views
5

創建一個python模塊,它讀入文件,刪除停用詞並輸出一個包含單詞及其頻率(在文檔中出現多少次)的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,'family':1,'give':1,'year':2,'weekend':1,'steve':1,'guests':1,'questions':1,'in ':2,'努力':1,'夥伴':1,'滅絕':1,'禮服':1,'children':4,'utans':1,'27':1,'raise': 1,'closet':1,'haired':2,'make':1,'humphreys':1,'親屬':1,'動物園':5,'瀕危':1,'星期日':1, 'special':1,'answer':1,'public':1,'意識':1,'計劃':1,'活動':1,'rhiona':1,'猩猩':4,'計劃':1,'leoni e':1,'orang':1,'yesterday':2,'free':2,'hand':1,'wild':1,'independent':1,'part':1,'準備' :1,'reveal':1,'day':1,'man':1,'picture':1,'keane':1,'animals':1,'14':1,'kevin':1 ,'16':1,'32':1,'age':1,'sibu':1,'dublin':2,'keepers':1,'face':1,'mujur':1,''紅色':2,'猩猩':1,'物種':1,'entry':1,'努力':1,'shows':1,'11am':1,'influx':1,'3pm' :1}

{'newest':1,'birth':2,'orang':1,'month':1,'steve':1,'questions':1,'utans':1, 'children':4,'staff':1,'limelight':1,'27':1,'based':1,'concerned':1,'sunday':1,'3pm':1,'finally ':1,'4':1,'maeve':1,'意識':1,'give':1,'activities':1,'giraffe':1,'臉譜':1,'準備': 1,'背景':1,'培育':1,'日':1,'首次登場':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,'條件':1,'public':1,'red':2,'shows':1,'orangutans':4,'free':2,'' '1','care':1,'sent':1,'great':1,'origin' :2,'計劃':1,'猩猩':1,'努力':1,'涌入':1,'命名':1,'家庭':1,'高興':1,'天氣':1 ,'客人':1,'滅絕':1,'post':1,'impressed':1,'raise':1,'reveal':1,'remain':1,'humphreys':1,''自信':1,'小牛':3,'入口':1,'shane':1,'part':1,'helen':1,'細心':1,'努力':1,'case' :1,'made':2,'animals':1,'14':1,'16':1,'ms':1,'wild':1,'savanna':1,'irish':1 ,'give':1,'resident':1,'suggestions':1,'slip':1,'in':2,'partner':1,'dress':1,'species':1, kevin':1,'rhiona':1,'make':1,'zoo':3,'瀕危':1,'親屬':1,'答案':1,'poor':1,'獨立' :1,'計劃':1,'l eonie':1,'time':1,'昨天':1,'hand':1,'hickey':1,'weekend':1,'man':1,'sibu':1,'age' :1,'穩定':2,'face':1,'禁閉':1,'african':2,'entry':1,'keane':1,'clarke':2,'left':1 }

但我需要從兩個文件或大量的文件中將兩個總計加在一起,以給出所有文件中單詞的總數,例如「動物園」。第一個文件zoo = 5第二個文件z​​oo = 3總數= 8。

我似乎無法計算出如何計算多個文件的文字而不是一次一個。

有什麼想法?

回答

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線是更好

我不理解爲什麼「[0]」在words = regex.findall(words)[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 

我不明白你的問題。請給精密度

+0

感謝您的改進解決方案,您能解釋一下defaultdict是什麼或來自哪裏?它只是在字典中保存當前不停的單詞!謝謝 – jenniem001 2011-03-23 15:30:44

+0

@ jenniem001 ** defaultdict **是從模塊**集合**導入的''dict''類型的子類。 ''d = defaultdict(int)''創建一個與普通字典相同的字典** d **,加上這個行爲:當** k **還不是** d **的關鍵字時,在表達式中使用'd [k]'會觸發在任何後續執行之前在字典** d **中創建一個項** k:0 **。如果** d **被定義爲'defaultdict(list)',則創建的項目是** k:[] **,等等。使用defaultdict可以減少代碼中的行數,使其更具可讀性 – eyquem 2011-03-23 16:46:35

2

fileinput模塊可讓您輕鬆處理多個文件。

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簡直就是爲每個輸入文件的詞對頻率圖的列表。

+0

什麼是字對頻圖? 你能解釋一下你的答案嗎?我只是對這部分程序感到困惑。謝謝 – jenniem001 2011-03-23 14:34:44

+0

字對頻地圖我的意思是您上面發佈的字典,即將單詞映射到文件中出現次數的字典。我上面的代碼合併了所有單個文件的數據。 – 2011-03-23 14:43:08

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