El progtwig Python que encuentra la palabra más frecuente en un archivo .txt, debe imprimir la palabra y su conteo

A partir de ahora, tengo una función para reemplazar la función countChars,

def countWords(lines): wordDict = {} for line in lines: wordList = lines.split() for word in wordList: if word in wordDict: wordDict[word] += 1 else: wordDict[word] = 1 return wordDict 

pero cuando ejecuto el progtwig, escupe esta abominación (esto es solo un ejemplo, hay cerca de dos páginas de palabras con un gran número de números al lado)

 before 1478 battle-field 1478 as 1478 any 1478 altogether 1478 all 1478 ago 1478 advanced. 1478 add 1478 above 1478 

Si bien, obviamente, esto significa que el código es lo suficientemente sólido como para ejecutarse, no estoy obteniendo lo que quiero. Necesita imprimir cuántas veces hay cada palabra en el archivo (gb.txt, que es la dirección de Gettysburg) Obviamente, cada palabra que está en el archivo no está allí exactamente 1478 veces …

Soy bastante nuevo en la progtwigción, así que estoy un poco perplejo ..

 from __future__ import division inputFileName = 'gb.txt' def readfile(fname): f = open(fname, 'r') s = f.read() f.close() return s.lower() def countChars(t): charDict = {} for char in t: if char in charDict: charDict[char] += 1 else: charDict[char] = 1 return charDict def findMostCommon(charDict): mostFreq = '' mostFreqCount = 0 for k in charDict: if charDict[k] > mostFreqCount: mostFreqCount = charDict[k] mostFreq = k return mostFreq def printCounts(charDict): for k in charDict: #First, handle some chars that don't show up very well when they print if k == '\n': print '\\n', charDict[k] #newline elif k == ' ': print 'space', charDict[k] elif k == '\t': print '\\t', charDict[k] #tab else: print k, charDict[k] #Normal character - print it with its count def printAlphabetically(charDict): keyList = charDict.keys() keyList.sort() for k in keyList: #First, handle some chars that don't show up very well when they print if k == '\n': print '\\n', charDict[k] #newline elif k == ' ': print 'space', charDict[k] elif k == '\t': print '\\t', charDict[k] #tab else: print k, charDict[k] #Normal character - print it with its count def printByFreq(charDict): aList = [] for k in charDict: aList.append([charDict[k], k]) aList.sort() #Sort into ascending order aList.reverse() #Put in descending order for item in aList: #First, handle some chars that don't show up very well when they print if item[1] == '\n': print '\\n', item[0] #newline elif item[1] == ' ': print 'space', item[0] elif item[1] == '\t': print '\\t', item[0] #tab else: print item[1], item[0] #Normal character - print it with its count def main(): text = readfile(inputFileName) charCounts = countChars(text) mostCommon = findMostCommon(charCounts) #print mostCommon + ':', charCounts[mostCommon] #printCounts(charCounts) #printAlphabetically(charCounts) printByFreq(charCounts) main() 

Si necesita contar varias palabras en un pasaje, entonces es mejor usar expresiones regulares.

Comencemos con un ejemplo simple:

 import re my_string = "Wow! Is this true? Really!?!? This is crazy!" words = re.findall(r'\w+', my_string) #This finds words in the document 

Resultado:

 >>> words ['Wow', 'Is', 'this', 'true', 'Really', 'This', 'is', 'crazy'] 

Tenga en cuenta que “Es” y “es” son dos palabras diferentes. Mi conjetura es que usted quiere que las cuente de la misma manera, de modo que podamos capitalizar todas las palabras y luego contarlas.

 from collections import Counter cap_words = [word.upper() for word in words] #capitalizes all the words word_counts = Counter(cap_words) #counts the number each time a word appears 

Resultado:

 >>> word_counts Counter({'THIS': 2, 'IS': 2, 'CRAZY': 1, 'WOW': 1, 'TRUE': 1, 'REALLY': 1}) 

¿Estás bien hasta aquí?

Ahora debemos hacer exactamente lo mismo que hicimos anteriormente, solo que esta vez estamos leyendo un archivo.

 import re from collections import Counter with open('your_file.txt') as f: passage = f.read() words = re.findall(r'\w+', passage) cap_words = [word.upper() for word in words] word_counts = Counter(cap_words) 

Este progtwig es en realidad un 4-liner, si utiliza las poderosas herramientas a su disposición:

 with open(yourfile) as f: text = f.read() words = re.compile(r"[\w']+", re.U).findall(text) # re.U == re.UNICODE counts = collections.Counter(words) 

La expresión regular encontrará todas las palabras, independientemente de la puntuación adyacente a ellas (pero contando los apóstrofes como parte de la palabra).

Un contador actúa casi como un diccionario, pero puede hacer cosas como counts.most_common(10) y agregar conteos, etc. Ver help(Counter)

También sugeriría que no haga que las funciones se printBy... , ya que solo las funciones sin efectos secundarios son fáciles de reutilizar.

 def countsSortedAlphabetically(counter, **kw): return sorted(counter.items(), **kw) #def countsSortedNumerically(counter, **kw): # return sorted(counter.items(), key=lambda x:x[1], **kw) #### use counter.most_common(n) instead # `from pprint import pprint as pp` is also useful def printByLine(tuples): print( '\n'.join(' '.join(map(str,t)) for t in tuples) ) 

Manifestación:

 >>> words = Counter(['test','is','a','test']) >>> printByLine( countsSortedAlphabetically(words, reverse=True) ) test 2 is 1 a 1 

edite para abordar el comentario de Mateusz Konieczny: reemplazó [a-zA-Z ‘] con [\ w’] … la clase de caracteres \ w, de acuerdo con los documentos de python, “Coincide con los caracteres de la palabra Unicode; esto incluye la mayoría de los caracteres que pueden ser parte de una palabra en cualquier idioma, así como los números y el guión bajo. Si se usa el indicador ASCII, solo se hace coincidir [a-zA-Z0-9_] “. (… pero aparentemente no coincide con un apóstrofe …) Sin embargo, \ w incluye _ y 0-9, así que si no los quieres y no estás trabajando con Unicode, puedes usar [a-zA -Z ‘]; Si está trabajando con Unicode, tendría que hacer una afirmación negativa o algo para restar [0-9_] de la clase de caracteres \ w

Tienes un simple error tipográfico, words donde quieres word .

Editar: Parece que has editado la fuente. Utilice copiar y pegar para hacerlo bien la primera vez.

Edición 2: al parecer, no eres el único propenso a los errores tipográficos. El problema real es que tienes lines donde quieres line . Me disculpo por acusarte de editar la fuente.

Aquí una posible solución, no tan elegante como la de ninjagecko pero aún así:

 from collections import defaultdict dicto = defaultdict(int) with open('yourfile.txt') as f: for line in f: s_line = line.rstrip().split(',') #assuming ',' is the delimiter for ele in s_line: dicto[ele] += 1 #dicto contians words as keys, word counts as values for k,v in dicto.iteritems(): print k,v 
  words = ['red', 'green', 'black', 'pink', 'black', 'white', 'black', 'eyes','white', 'black', 'orange', 'pink', 'pink', 'red', 'red', 'white', 'orange', 'white', "black", 'pink', 'green', 'green', 'pink', 'green', 'pink','white', 'orange', "orange", 'red'] from collections import Counter counts = Counter(words) top_four = counts.most_common(4) print(top_four)