2017-02-07 23 views
2

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

Если я:

from nltk import word_tokenize 
test_str = "Some Co Inc. Other Co L.P." 
word_tokenize(test_str) 
Out[1]: ['Some', 'Co', 'Inc.', 'Other', 'Co', 'L.P', '.'] 

последний "" помещается в свой собственный токен. Однако, если вместо этого есть другое слово в конце, последнее «.» сохраняется:

from nltk import word_tokenize 
test_str = "Some Co Inc. Other Co L.P. Another Co" 
word_tokenize(test_str) 
Out[1]: ['Some', 'Co', 'Inc.', 'Other', 'Co', 'L.P.', 'Another', 'Co'] 

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

from nltk import word_tokenize 
test_str = "Some Co Inc. Other Co L.P." 
word_tokenize(test_str + " |||") 

так как я чувствую себя довольно уверенно в том, чтобы выбрасывать «|||» в любой момент времени, но не знаю, какую другую пунктуацию я могу захотеть сохранить, которая может быть удалена. Есть ли лучший способ сделать это?

ответ

0

Не могли бы вы использовать re?

import re 

test_str = "Some Co Inc. Other Co L.P." 

print re.split('\s', test_str) 

Это разделит входную строку на основе интервала, сохранив вашу пунктуацию.

+0

Почему бы не использовать 'test_str.split()' вместо этого? Он не вводит пустые токены между повторяющимися пробелами, а также удаляет ведущие и конечные пробелы. – lenz

3

Это причуда написания, что если предложение заканчивается сокращенным словом, мы пишем только один период, а не два. Маркер nltk не «удаляет» его, он отделяет его, потому что структура предложения («предложение должно заканчиваться периодом или другой подходящей пунктуацией») более важна для инструментов NLP, чем согласованное представление сокращений. Токенизатор достаточно умен, чтобы распознавать большинство сокращений, поэтому он не отделяет период в L.P. в середине предложения.

Ваше решение с ||| приводит к непоследовательной структуре предложения, так как теперь у вас нет окончательной пунктуации предложения. Лучшим решением было бы добавить отсутствующий период только после аббревиатур. Вот один из способов сделать это, некрасиво, но так надежно, как собственная аббревиатуру распознаватель в Tokenizer в:

toks = nltk.word_tokenize(test_str + " .") 
if len(toks) > 1 and len(toks[-2]) > 1 and toks[-2].endswith("."): 
    pass # Keep the added period 
else: 
    toks = toks[:-1] 

PS. Решение, которое вы приняли, полностью изменит токенизацию, оставив все пунктуацию, прикрепленную к соседнему слову (наряду с другими нежелательными эффектами, такими как ввод пустых токенов). Скорее всего, это не то, что вы хотите.

+0

Вы должны добавить проверку, что предложение имеет не менее двух токенов перед доступом к 'toks [-2]' (или catch исключение). – lenz

+0

Это имеет смысл - но для того, что я пытаюсь сделать, я действительно хотел, чтобы все символы и пунктуация были привязаны к соседнему слову, как есть. Я просто перерабатывал, когда на самом деле re.split или str.split было бы в порядке. – NikT

+0

@ lenz, хорошая точка. Хотя, поскольку я только что добавил токен, предложение будет иметь по крайней мере два токена, если только он не будет пустым. :-) – alexis