2011-03-23 14 views
5

Creó un módulo python que lee en un archivo, elimina las palabras de detención y emite un diccionario python con la palabra y su frecuencia (Cuántas veces ocurrió en el documento).Frecuencia de recuento de palabras en documentos usando python regex

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 

Imprime todas las palabras 'non-stop' dentro de ese archivo y la frecuencia en que se producen en el archivo: La salida será similar a:

{{ 'Sábado': 1, 'irlandés': 1, 'familia': 1, 'dar': 1, 'año': 2, 'fin de semana': 1, 'steve': 1, 'invitados': 1, 'preguntas': 1, 'en ': 2,' esfuerzo ': 1,' pareja ': 1,' extinción ': 1,' vestimenta ': 1,' niños ': 4,' utans ': 1,' 27 ': 1,' subir ': 1, 'closet': 1, 'haired': 2, 'make': 1, 'humphreys': 1, 'relatives': 1, 'zoo': 5, 'endangered': 1, 'sunday': 1, 'especial': 1, 'respuesta': 1, 'público': 1, 'conciencia': 1, 'planeado': 1, 'actividades': 1, 'rhiona': 1, 'orangutanes': 4, 'planes ': 1,' leoni e ': 1,' orang ': 1,' ayer ': 2,' gratis ': 2,' mano ': 1,' salvaje ': 1,' independiente ': 1,' parte ': 1,' preparación ' : 1, 'revelado': 1, 'día': 1, 'hombre': 1, 'imagen': 1, 'keane': 1, 'animales': 1, '14': 1, 'kevin': 1 , '16': 1, '32': 1, 'edad': 1, 'sibu': 1, 'dublin': 2, 'keepers': 1, 'cara': 1, 'mujur': 1, ' rojo ': 2,' orangután ': 1,' especie ': 1,' entrada ': 1,' esfuerzos ': 1,' muestra ': 1,' 11am ': 1,' afluencia ': 1,' 3pm ' : 1}

{'más nuevo': 1, 'nacimiento': 2, 'orang': 1, 'mes': 1, 'steve': 1, 'preguntas': 1, 'utans': 1, 'niños': 4, 'personal': 1, 'candelero': 1, '27': 1, 'basado': 1, 'preocupado': 1, 'domingo': 1, '3pm': 1, 'finalmente ': 1,' 4 ': 1,' maeve ': 1,' conciencia ': 1,' dio ': 1,' actividades ': 1,' jirafa ': 1,' facebook ': 1,' preparando ': 1, 'fondo': 1, 'nutrir': 1, 'día': 1, 'debut': 1, 'rothschild': 1, 'keepers': 1, 'email': 1, 'pasos': 1, '11am': 1, 'página': 1, 'foto': 1, 'nacido' : 1, 'resultado': 1, 'año': 2, 'sábado': 1, 'especial': 1, 'closet': 1, 'cabello': 2, 'sección': 1, 'bennet': 2 , 'mum': 3, 'mujur': 1, 'condiciones': 1, 'public': 1, 'red': 2, 'shows': 1, 'orangutans': 4, 'free': 2, ' guardián ': 1,' noviembre ': 1,' cuidado ': 1,' envío ': 1,' excelente ': 1,' orígenes ': 1,' 32 ': 1,' invitado ': 1,' dublín ' : 2, 'planeado': 1, 'orangután': 1, 'esfuerzos': 1, 'afluencia': 1, 'nombrado': 1, 'familia': 1, 'encantado': 1, 'clima': 1 , 'invitados': 1, 'extinción': 1, 'publicación': 1, 'impresionado': 1, 'aumento': 1, 'revelado': 1, 'permanecido': 1, 'humphreys': 1, ' confidente ': 1,' ternero ': 3,' entrada ': 1,' shane ': 1,' parte ': 1,' helen ': 1,' atento ': 1,' esfuerzo ': 1,' caso ' : 1, 'hecho': 2, 'animales': 1, '14': 1, '16': 1, 'ms': 1, 'salvaje': 1, 'sabana': 1, 'irlandés': 1 , 'give': 1, 'resident': 1, 'suggestions': 1, 'slip': 1, 'in': 2, 'partner': 1, 'dress': 1, 'species': 1, ' kevin ': 1,' rhiona ': 1,' hacer ': 1,' zoológico ': 3,' en peligro ': 1,' parientes ': 1,' respuesta ': 1,' pobre ': 1,' independiente ' : 1, 'planes': 1, 'l eonie ': 1,' tiempo ': 1,' ayer ': 1,' mano ': 1,' hickey ': 1,' fin de semana ': 1,' hombre ': 1,' sibu ': 1,' edad ' : 1, 'estable': 2, 'cara': 1, 'confinamiento': 1, 'africano': 2, 'entrada': 1, 'keane': 1, 'clarke': 2, 'izquierda': 1 }

Pero necesito que se agreguen ambos totales de ambos archivos o cantidades numerosas de archivos para dar un recuento total de la palabra, por ejemplo, "zoo" en todos los archivos. 1st archivo zoo = 5 2do archivo zoo = 3 total = 8.

Parece que no puedo entender cómo cuento las palabras para muchos archivos en lugar de solo uno a la vez.

¿Alguna idea ?!

Respuesta

2

La barra invertida en '<\/?[ap][^>]*>' es inútil porque '/' no es un carácter especial

'[^\w]' es '\W' Por la forma en que '[^\w]+' será más eficiente que una sola '[^\w]'

re.DOTALL es inútil con r'<\/?[ap][^>]*>' ya que no hay punto en esta RE

Si lo hace words = f.read().lower() para bajar las cartas, no es necesario re.IGNORECASE

RE para la sustitución se puede poner en un RE: reg123 = re.compile(r'(</?[ap][^>]*>|&quot;|\W+)')

archivo no es un buen nombre para el nombre de un archivo, se anula el nombre de una función incorporada existente

la sustitución de la líneas de código para obtener htmfiles por una expresión generadora es mejor

No entiendo por qué '[0]' en words = regex.findall(words)[0]

También puede agrupar las palabras de palabras vacías en el RE se utiliza para sustituir la ' ':

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

que se incluirán en el RE para la sustitución

la sangría de filewords[file] = freq es malo

.

Le propongo la siguiente mejora; No lo probé, porque no soy el archivo para tratar. Ciertamente no es perfecto. Pida puntos confusos.

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 

No entendí muy bien su pregunta. Por favor, brinde precisiones

+0

gracias por su solución de mejora, ¿podría explicarnos qué es defaultdict o de dónde viene? ¿Tiene las palabras actuales sin parar en un diccionario? Gracias – jenniem001

+0

@ jenniem001 ** defaultdict ** es una subclase del tipo '' dict'', importada del módulo ** collections **. '' d = defaultdict (int) '' crea un diccionario ** d ** que actúa igual que un diccionario normal, más este comportamiento: cuando ** k ** aún no es una clave de ** d **, el el uso de 'd [k]' en una expresión activa la creación de un elemento ** k: 0 ** en el diccionario ** d ** antes de cualquier ejecución posterior. Si ** d ** se definió como 'defaultdict (list)', el elemento creado es ** k: [] **, y etc. El empleo de un valor predeterminado permite reducir el número de líneas en un código, lo hace más legible – eyquem

2

El módulo fileinput le permite manejar fácilmente varios archivos.

0

Una posible solución sería

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

... donde dictionaries es simplemente una lista de mapas de Word a la frecuencia para cada uno de los archivos de entrada.

+0

¿Qué es un mapa de palabra a frecuencia? ¿Podría explicar su respuesta? Estoy un poco confundido en esta parte del programa. Gracias – jenniem001

+0

Por mapa de palabra a frecuencia me refiero exactamente al diccionario que publicó anteriormente, es decir, uno que asigna una palabra al número de ocurrencias en un archivo. Mi código anterior combina los datos de todos los archivos individuales. –

0

asumiendo files es una lista de frecuencia para cada archivo que tiene, intente algo como:

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