2017-05-22 4 views
0

Ce code produit n-grammes et le nombre de comptages le n gramme apparaît. J'ai un fichier csv avec des lignes et une colonne contenant une chaîne de mots pour chaque ligne. Ce code par exemple quand il recherche obtient un gramme de 4 comme 'ceci est mon chiot' il compte également le nombre d'occurrences il se produit dans cette même ligne. Mon intention est que quand il obtient une occurrence de n-gramme dans une rangée il devrait la compter une fois et compter sa deuxième fois dans une autre rangée et ainsi de suite. Donc, ce code compte «ceci est mon chiot» 3 fois. Pourtant, je veux que ce soit 2 foissupprimer les doublons de n grammes dans les lignes python

Ce code python

import collections 
import re 
import sys 
import time 


def tokenize(string): 
    """Convert string to lowercase and split into words (ignoring 
    punctuation), returning list of words. 
    """ 
    return re.findall(r'\w+', string.lower()) 


def count_ngrams(lines, min_length=4, max_length=5): 
    """Iterate through given lines iterator (file object or list of 
    lines) and return n-gram frequencies. The return value is a dict 
    mapping the length of the n-gram to a collections.Counter 
    object of n-gram tuple and number of times that n-gram occurred. 
    Returned dict includes n-grams of length min_length to max_length. 
    """ 
    lengths = range(min_length, max_length + 1) 
    ngrams = {length: collections.Counter() for length in lengths} 
    queue = collections.deque(maxlen=max_length) 

    # Helper function to add n-grams at start of current queue to dict 
    def add_queue(): 
     current = tuple(queue) 
     for length in lengths: 
      if len(current) >= length: 
       ngrams[length][current[:length]] += 1 

    # Loop through all lines and words and add n-grams to dict 
    for line in lines: 
     for word in tokenize(line): 
      queue.append(word) 
      if len(queue) >= max_length: 
        add_queue() 

    # Make sure we get the n-grams at the tail end of the queue 
    while len(queue) > min_length: 
     queue.popleft() 
     add_queue() 

    return ngrams 


def print_most_frequent(ngrams, num=10): 
    """Print num most common n-grams of each length in n-grams dict.""" 
    for n in sorted(ngrams): 
     print('----- {} most common {}-grams -----'.format(num, n)) 
     for gram, count in ngrams[n].most_common(num): 
      print('{0}: {1}'.format(' '.join(gram), count)) 
     print('') 


if __name__ == '__main__': 
    if len(sys.argv) < 2: 
     print('Usage: python ngrams.py filename') 
     sys.exit(1) 

    start_time = time.time() 
    with open("PWorm.csv") as f: 
     ngrams = count_ngrams(f) 
    print_most_frequent(ngrams) 
    elapsed_time = time.time() - start_time 
    print('Took {:.03f} seconds'.format(elapsed_time)) 

Votre aide sera très appréciée. Merci

Répondre

0

Au lieu de vous peuplant ngrams semi-manuelle, vous pouvez utiliser un defaultdict

Pour éviter que les mêmes ngram en ligne pour compter deux fois, vous devrez faire une ngram-dict par ligne, puis combiner avec le ngram général dict

def count_ngrams(lines, min_length=4, max_length=5): 
    """Iterate through given lines iterator (file object or list of 
    lines) and return n-gram frequencies. The return value is a dict 
    mapping the length of the n-gram to a collections.Counter 
    object of n-gram tuple and number of times that n-gram occurred. 
    Returned dict includes n-grams of length min_length to max_length. 
    """ 
    lengths = range(min_length, max_length + 1) 
    ngrams = collections.defaultdict(collections.Counter) 
    queue = collections.deque(maxlen=max_length) 

    # Helper function to add n-grams at start of current queue to dict 
    def add_queue(ngrams_line): 
     current = tuple(queue) 
     for length in lengths: 
      if len(current) >= length: 
       ngrams_line[length][current[:length]] = 1 # instead of += 1 

    # to combine the 2 defaultdict(Counter)    
    def combine_ngrams(ngram, ngramline): 
     for k, v in ngramsline.items(): 
      ngrams[k] += v 
     return ngrams 

    # Loop through all lines and words and add n-grams to dict 
    for line in lines: 
     ngrams_line = collections.defaultdict(collections.Counter) 
     for word in tokenize(line): 
      queue.append(word) 
      if len(queue) >= max_length: 
        add_queue(ngrams_line) 
     ngrams = combine_ngrams(ngrams, ngrams_line) 


    # Make sure we get the n-grams at the tail end of the queue 
    ngrams_line = collections.defaultdict(collections.Counter) 
    while len(queue) > min_length: 
     queue.popleft() 
     add_queue(ngrams_line) 
    ngrams = combine_ngrams(ngrams, ngrams_line) 

    return ngrams 

Je ne comprends pas 100% de la partie après while len(queue) > min_length:, ou pourquoi l'queue ne sont pas remis à zéro everyline, vous vous pourriez avoir à ajuster ma réponse une bit

+0

Merci beaucoup pour votre aide. Cela a fonctionné comme j'en avais besoin. Merci encore une fois – ninyesiga