Как использовать стоп-слово при предварительной обработке txt-файла

Я пытаюсь написать код, который будет обрабатывать текст и в конечном итоге индексировать их все. Сначала мне нужно удалить неалфавитные символы и знаки препинания и преобразовать заглавные буквы в строчные, а затем удалить стоп-слова.

Вот что я сделал до сих пор:

from stopwords import *

def removeStopwords(wordlist, flag):
    return [w for w in wordlist if w not in flag]

def preprocessing():
    import re
    with open('44.txt', 'r', encoding = 'utf8') as data:
        for line in data:
            a = line.rstrip().lower()
            result = re.sub('[^a-zA-Z]', ' ', a)
            b = removeStopwords(result, stopwords)
            print(b)

if __name__ == '__main__':
    preprocessing()

Затем я получаю, что все буквы разбиваются на части, такие как ['a'], ['w'], ['o'], ['l'], ['f']

stopwords.py — это просто список слов, например:

stopwords = ['a', 'are', 'aren t', ....]

Может кто-нибудь сказать мне, что происходит?

Спасибо за ваше время !


person zakels    schedule 11.04.2015    source источник
comment
В чем проблема с тем, что вы сделали до сих пор? Какие части работают, где что-то идет не так, и где вы застряли в исправлении?   -  person abarnert    schedule 11.04.2015
comment
Если я удалю все части стоп-слов и напечатаю (результат), все будет работать нормально. Я просто не знаю, как правильно применять стоп-слова из источника   -  person zakels    schedule 11.04.2015


Ответы (2)


Список слов — это просто строка. Когда вы делаете

w for w in wordlist if w not in flag

Он перебирает каждый символ строки, поэтому вы получаете отдельные алфавиты. Преобразуйте wordlist в список перед переходом к removeStopwords.

def preprocessing():
    import re
    with open('44.txt', 'r', encoding = 'utf8') as data:
        for line in data:
            a = line.rstrip().lower()
            result = re.sub('[^a-zA-Z]', ' ', a)
            result = result.split()#creates a list of words
            b = removeStopwords(result, stopwords)
            print(b)
person avinash pandey    schedule 11.04.2015
comment
Это то же самое, что и ответ jedwards, и у него точно такая же проблема: ни одно из слов в result.split() не может соответствовать стоп-слову, такому как "aren t". - person abarnert; 11.04.2015
comment
@zakels: Нет, не так. Попробуйте это с Эти примеры не очень хороши. Это не удалит нет. - person abarnert; 11.04.2015
comment
@abarnert извините, когда я написал ответ, ответа Джедвардса там не было .. Думаю, он удалил его, пока я его писал. Даже сейчас он не отображается .. - person avinash pandey; 11.04.2015
comment
@avinashpandey: Да, он удалил именно из-за этой проблемы. - person abarnert; 11.04.2015
comment
@abarnert Я понимаю, но я думаю, что главная проблема заключалась в том, почему он возвращал список символов вместо списка слов. - person avinash pandey; 11.04.2015

Ваша первая проблема, как объясняет jedward answer, заключается в том, что, несмотря на вводящее в заблуждение имя wordlist, вы передаете removeStopwords не список слов, это строка — последовательность отдельных символов.

Если бы ваш список стоп-слов состоял исключительно из отдельных слов, решение было бы простым: разбить строку на слова, а затем удалить слова, соответствующие стоп-листу.

К сожалению, если в стоп-листе есть такие слова, как aren t, это не сработает — "These examples aren't good" будет предварительно обработано и разделено на "these examples aren t good", которое разделится на ["these", "examples", "aren", "t", "good"], и, очевидно, ни одно из этих слов не соответствует "aren t".

Идеальным решением было бы убрать пунктуацию внутри слова вместо того, чтобы преобразовывать ее в пробелы. Что-то вроде этого:

result = re.sub('[^a-zA-Z]', ' ', re.sub("['_]", '', a))

Тогда вы получите "these examples arent good", и (при условии, что вы напишете стоп-слово как "arent" вместо "aren t") простое решение все еще работает. Однако это может не соответствовать вашим требованиям — это изменение правил.

Итак, допустим, мы не можем этого сделать. Затем, если вы хотите упростить задачу, вам нужно отфильтровать подпоследовательности, а не только отдельные слова.

Итак, что-то вроде этого:

def removeStopwords(line, stopwords):
    result = []
    wordlist = line.split()
    i = 0
    while i < len(wordlist):
        for stopword in stopwords:
            stopwordlist = stopword.split()
            if wordlist[i:i+len(stopwordlist)] == stopwordlist:
                i += len(stopwordlist)
                break
        else:
            result.append(wordlist[i])
            i += 1
    return ' '.join(result)

Если вам нужно, чтобы это было быстрее, вам нужно предварительно обработать stopwords в лучшую структуру данных, например, в дерево, которое можно быстро сканировать на предмет совпадения префиксов.

person abarnert    schedule 11.04.2015
comment
Извините за задержку с ответом. Я полностью понимаю, в чем проблема. Я не заметил, что у меня были проблемы со стоп-словами вроде are t, потому что следующим шагом было удаление слов длиной меньше 3. Спасибо за пост! - person zakels; 11.04.2015