Диктовка / просмотр списка по тексту тада - PullRequest
1 голос
/ 01 октября 2019

Мне нужно обработать список из четырех тысяч строк, где каждая строка представляет документ. Моя цель состоит в том, чтобы подсчитать, сколько документов появляется в каждом слове, и возвращать вхождение:

{word: number_of_docs_appeared}.

Я написал два разных подхода, которые хорошо работают для небольшого списка документов. Один использует базовую итерацию и условные выражения, а другой использует понимания и некоторые функциональные возможности, такие как лямбда и карта. Ниже приведены две версии:

Метод 1

def corpus_word_frequency(corpus_text):

    bag_of_words = " ".join(corpus_text).split()
    tokens = set(bag_of_words)

    words_frequency = {}

    for doc in corpus_text:
        text = doc.split()

        for word in tokens:
            if word in text:
                if word in words_frequency.keys():
                    words_frequency[word] += 1
                else:
                    words_frequency[word] = 1

    return words_frequency

Метод 2

def corpus_word_frequency(corpus_text):
    """docstring"""

    bag_of_words = " ".join(corpus_text).split()
    tokens = set(bag_of_words)

    return {
        token: sum(
            map(lambda doc: 1 if token in doc.split() else 0, corpus_text))
        for token in tokens
    }

Проблема в следующем: метод 1 медленный для моего случая, но выполним, но метод2 Я просто не мог дождаться конца, это слишком много. Итак, проблема в понимании списка? использование карты и лямбда? что-то другое? Есть ли способ сделать метод 2 более эффективным?

1 Ответ

0 голосов
/ 01 октября 2019

Используя образец файла Lorem Ipsum , я сравнил вашу функцию со встроенной collections.Counter:

In [1]: from collections import Counter

In [2]: def method1(corpus_text): 
   ...:     bag_of_words = " ".join(corpus_text).split() 
   ...:     tokens = set(bag_of_words) 
   ...:     words_frequency = {} 
   ...:     for doc in corpus_text: 
   ...:         text = doc.split() 
   ...:         for word in tokens: 
   ...:             if word in text: 
   ...:                 if word in words_frequency.keys(): 
   ...:                     words_frequency[word] += 1 
   ...:                 else: 
   ...:                     words_frequency[word] = 1 
   ...:     return words_frequency 

In [3]: def method2(corpus_text): 
   ...:     bag_of_words = " ".join(corpus_text).split() 
   ...:     tokens = set(bag_of_words) 
   ...:     return { 
   ...:         token: sum( 
   ...:             map(lambda doc: 1 if token in doc.split() else 0, corpus_text)) 
   ...:         for token in tokens 
   ...:     }

In [4]: with open("Latin-Lipsum.txt") as file:
   ...:     text = file.read()

In [5]: method1(text)
Out[5]:
{'L': 1,
 'o': 63,
 'r': 72,
 ...
 'O': 1,
 'P': 1,
 'j': 1}

In [6]: Counter(text)
Out[6]:
Counter({'L': 1,
         'o': 63,
         'r': 72,
         ...
         'O': 1,
         'P': 1,
         'j': 1})

Они работают почти одинаково, за исключением того, чтоCounter также подсчитывает \n символов в этом случае.

Хотя с точки зрения скорости, Counter намного быстрее:

In [7]: %timeit method1(text)                                                                                                      
1.96 ms ± 32.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In [8]: %timeit method2(text)                                                                                                      
10.5 ms ± 19.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [9]: %timeit Counter(text)                                                                                                      
43.8 µs ± 50.4 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

Ваш второй метод действительно медленнее, чемваш первый метод, и Counter намного быстрее, чем оба.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...