Лемматизация в понимании списка, если слово меньше X - PullRequest
1 голос
/ 17 января 2020

У меня есть следующая функция, которая получает список токенов слов, собирает тэг частей речи в формате, читаемом по Wor dNet, и использует его для лемматизации каждого токена - я применяю это к списку списков токенов слов:

from nltk import pos_tag
from nltk.stem import WordNetLemmatizer
from nltk.corpus import wordnet as wn

def getWordNetPOS (POStag):
    def is_noun(POStag):
        return POStag in ['NN', 'NNS', 'NNP', 'NNPS']
    def is_verb(POStag):
        return POStag in ['VB', 'VBD', 'VBG', 'VBN', 'VBP', 'VBZ']
    def is_adverb(POStag):
        return POStag in ['RB', 'RBR', 'RBS']
    def is_adjective(POStag):
        return POStag in ['JJ', 'JJR', 'JJS']

    if is_noun(POStag):
        return wn.NOUN
    elif is_verb(POStag):
        return wn.VERB
    elif is_adverb(POStag):
        return wn.ADV
    elif is_adjective(POStag):
        return wn.ADJ
    else:
        # if not noun, verb, adverb or adjective, return noun
        return wn.NOUN

# lemmatize word tokens
def lemmas (wordtokens):
    lemmatizer = WordNetLemmatizer()
    POStag = pos_tag(wordtokens)
    wordtokens = [lemmatizer.lemmatize(token[0], getWordNetPOS(token[1]))
                  for token in POStag]

    return wordtokens

lemmatizedList = []
mylist = [['this','is','my','first','sublist'],['this','is','my','second','sublist']]

for ls in mylist:
    x = lemmas(ls)
    lemmatizedList.append(x)

Я хочу найти способ ограничить лемматизацию токенами заданной длины (т. е. 2), но, что важно, я также хочу сохранить исходную форму любых слов, меньших этого порог. Самое близкое, что у меня есть, это добавить if len(token[0])>2 в конец списка wordtokens в функции lemmas, но это возвращает только лемматизированные токены. Точно так же я пытался добавить что-то похожее на else token for token in POStag после оператора if, но я получаю синтаксическую ошибку. Для ясности это то, что я имею в виду:

wordtokens = [lemmatizer.lemmatize(token[0], getWordNetPOS(token[1]))
              for token in POStag if len(token[0])>2
              else token for token in POStag]

Я надеюсь, что это простая ошибка и немного "1014 * слепое пятно с моей стороны.

1 Ответ

2 голосов
/ 17 января 2020

Это действительно просто «слепое пятно».

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

wordtokens = [lemmatizer.lemmatize(token[0], getWordNetPOS(token[1])) if len(token[0]) > 2 else token
              for token in POStag]

Объяснение:

Понимание списка должно сохранять все токены, поэтому вы не хотите добавлять условие с помощью if.

wordtokens = [<tokenoperation> for token in POStag]

Теперь вы хотите изменить операцию на основе длины токена, поэтому вы изменяете только часть tokenoperation, так что она изменяет только токен:

lemmatizer.lemmatize(token[0], getWordNetPOS(token[1])) if len(token[0]) > 2 else token

Вы также можете добавить несколько таких паратезов, чтобы сделать их более понятными:

wordtokens = [
    (
        lemmatizer.lemmatize(token[0], getWordNetPOS(token[1]))
        if len(token[0]) > 2
        else token
    )
    for token in POStag
]

Некоторая документация / примеры: см. Раздел Использование условной логики c на этой реальной python .com странице.

...