Обход лингвистического дерева NLTK и извлечение имен существительных (NP)
Я создал чанкер на основе пользовательского классификатора: DigDug_classifier
, который кусками следующее предложение:
sentence = "There is high signal intensity evident within the disc at T1."
Чтобы создать эти куски:
(S
(NP There/EX)
(VP is/VBZ)
(NP high/JJ signal/JJ intensity/NN evident/NN)
(PP within/IN)
(NP the/DT disc/NN)
(PP at/IN)
(NP T1/NNP)
./.)
Мне нужно создать список только NP из вышеупомянутого, как это:
NP = ['There', 'high signal intensity evident', 'the disc', 'T1']
Я написал следующий код:
output = []
for subtree in DigDug_classifier.parse(pos_tags):
try:
if subtree.label() == 'NP': output.append(subtree)
except AttributeError:
output.append(subtree)
print(output)
Но это дает мне ответ вместо этого:
[Tree('NP', [('There', 'EX')]), Tree('NP', [('high', 'JJ'), ('signal', 'JJ'), ('intensity', 'NN'), ('evident', 'NN')]), Tree('NP', [('the', 'DT'), ('disc', 'NN')]), Tree('NP', [('T1', 'NNP')]), ('.', '.')]
Что я могу сделать, чтобы получить желаемый ответ?
2 ответа
Решение
Во-первых, смотрите Как пройти объект дерева NLTK?
Конкретный к вашему вопросу добыча НП:
>>> from nltk import Tree
>>> parse_tree = Tree.fromstring("""(S
... (NP There/EX)
... (VP is/VBZ)
... (NP high/JJ signal/JJ intensity/NN evident/NN)
... (PP within/IN)
... (NP the/DT disc/NN)
... (PP at/IN)
... (NP T1/NNP)
... ./.)""")
# Iterating through the parse tree and
# 1. check that the subtree is a Tree type and
# 2. make sure the subtree label is NP
>>> [subtree for subtree in parse_tree if type(subtree) == Tree and subtree.label() == "NP"]
[Tree('NP', ['There/EX']), Tree('NP', ['high/JJ', 'signal/JJ', 'intensity/NN', 'evident/NN']), Tree('NP', ['the/DT', 'disc/NN']), Tree('NP', ['T1/NNP'])]
# To access the item inside the Tree object,
# use the .leaves() function
>>> [subtree.leaves() for subtree in parse_tree if type(subtree) == Tree and subtree.label() == "NP"]
[['There/EX'], ['high/JJ', 'signal/JJ', 'intensity/NN', 'evident/NN'], ['the/DT', 'disc/NN'], ['T1/NNP']]
# To get the string representation of the leaves
# use " ".join()
>>> [' '.join(subtree.leaves()) for subtree in parse_tree if type(subtree) == Tree and subtree.label() == "NP"]
['There/EX', 'high/JJ signal/JJ intensity/NN evident/NN', 'the/DT disc/NN', 'T1/NNP']
# To just get the leaves' string,
# iterate through the leaves and split the string and
# keep the first part of the "/"
>>> [" ".join([leaf.split('/')[0] for leaf in subtree.leaves()]) for subtree in parse_tree if type(subtree) == Tree and subtree.label() == "NP"]
['There', 'high signal intensity evident', 'the disc', 'T1']
небольшая модификация ответа Альваса выше - просто получить строку листьев
[" ".join([leaf.split('/')[0] for leaf in subtree.leaves()]) for subtree in parse_tree if type(subtree) == Tree and subtree.label() == "NP"]
может выдать ошибку, поскольку лист является объектом кортежа и не имеет атрибута split(). Вместо этого должно быть
leaf[0].split('/')[0]