Удалить список стоп-слов из счетчика в Python

У меня есть функция в NLTK для создания списка соответствия, который будет выглядеть

concordanceList = ["this is a concordance string something", 
               "this is another concordance string blah"] 

и у меня есть другая функция, которая возвращает словарь счетчика с количеством каждого слова в concordanceList

def mostCommonWords(concordanceList):
  finalCount = Counter()
  for line in concordanceList:
    words = line.split(" ")
    currentCount = Counter(words)
    finalCount.update(currentCount)
  return finalCount

Проблема у меня заключается в том, как лучше всего удалить стоп-слова из полученного счетчика, чтобы при вызове

mostCommonWords(concordanceList).most_common(10)

результат не просто {"the": 100, "is": 78, "that": 57}.

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

stopWordCounter = Counter(the=1, that=1, so=1, and=1)
processedWordCounter = mostCommonWords(concordanceList) & stopWordCounter

который должен установить значения счетчика для всех стоп-слов в 1, но это выглядит странно.

Изменить: Кроме того, у меня возникают проблемы на самом деле сделать такой stopWordCounter, потому что, если я хочу включить зарезервированные слова, такие как "и", я получаю недопустимую синтаксическую ошибку. Счетчики имеют простые в использовании методы объединения и пересечения, которые делают задачу довольно простой; Есть ли эквивалентные методы для словарей?

6 ответов

Решение

Вы можете удалить стоп-слова во время токенизации...

stop_words = frozenset(['the', 'a', 'is'])
def mostCommonWords(concordanceList):
    finalCount = Counter()
    for line in concordanceList:
        words = [w for w in line.split(" ") if w not in stop_words]
        finalCount.update(words)  # update final count using the words list
    return finalCount

Во-первых, вам не нужно создавать все эти новые Counterвнутри вашей функции; ты можешь сделать:

for line in concordanceList:
    finalCount.update(line.split(" "))

вместо.

Во-вторых, Counter это своего рода словарь, поэтому вы можете удалять элементы напрямую:

for sword in stopwords:
    del yourCounter[sword]

Неважно, sword находится в Counter - это не вызовет исключения независимо.

Я бы пошел на сглаживание элементов в слова, игнорируя любые стоп-слова и предоставляя это в качестве входных данных для одного Counter вместо:

from collections import Counter
from itertools import chain

lines = [
    "this is a concordance string something", 
    "this is another concordance string blah"
]

stops = {'this', 'that', 'a', 'is'}    
words = chain.from_iterable(line.split() for line in lines)
count = Counter(word for word in words if word not in stops)

Или этот последний бит можно сделать так:

from itertools import ifilterfalse
count = Counter(ifilterfalse(stops.__contains__, words))

Лично я думаю, что ответ @JonClements был самым элегантным. Кстати, уже есть список stopwords в NLTK, на случай, если OP не знает, смотрите проблему удаления стоп-слова NLTK

from collections import Counter
from itertools import chain
from nltk.corpus import stopwords

lines = [
    "this is a concordance string something", 
    "this is another concordance string blah"
]

stops = stopwords.words('english')
words = chain.from_iterable(line.split() for line in lines)
count = Counter(word for word in words if word not in stops)
count = Counter(ifilterfalse(stops.__contains__, words))

Так же FreqDist модуль в НЛТК имеет больше связанных с НЛП функций по сравнению с collections.Counter, http://nltk.googlecode.com/svn/trunk/doc/api/nltk.probability.FreqDist-class.html

Как насчет:

if 'the' in counter:
    del counter['the']

У вас есть несколько вариантов.

Во-первых, не считайте стоп-слова при обновлении Counter - что вы можете сделать более кратко, так как Counter объекты могут принимать итеративное, а также другое отображение для update:

def mostCommonWords(concordanceList):
    finalCount = Counter()
    stopwords = frozenset(['the', 'that', 'so'])
    for line in concordanceList:
        words = line.strip().split(' ')
        finalCount.update([word for word in words if word not in stopwords])
    return finalCount

Кроме того, вы можете использовать del на самом деле удалить их из Counter как только вы закончите.

Я также добавил strip позвонить на line до split, Если бы вы были использовать split() и поведение разделения по умолчанию на все пустое пространство, вам это не нужно, но split(' ') не будет рассматривать символ новой строки как разделенный, поэтому последнее слово каждой строки будет иметь конечный символ \n и будет считаться отличным от любых других явлений. strip избавится от этого.

Другие вопросы по тегам