Wie entferne ich die Interpunktion mit dem NLTK-Tokenizer?


125

Ich fange gerade an, NLTK zu verwenden, und ich verstehe nicht ganz, wie man eine Liste von Wörtern aus Text erhält. Wenn ich benutze nltk.word_tokenize(), bekomme ich eine Liste mit Wörtern und Satzzeichen. Ich brauche stattdessen nur die Worte. Wie kann ich Interpunktion loswerden? Funktioniert auch word_tokenizenicht mit mehreren Sätzen: Punkte werden zum letzten Wort hinzugefügt.


12
Warum entfernen Sie die Interpunktion nicht selbst? nltk.word_tokenize(the_text.translate(None, string.punctuation))sollte in Python2 funktionieren, während Sie dies in Python3 tun können nltk.work_tokenize(the_text.translate(dict.fromkeys(string.punctuation))).
Bakuriu

3
Das funktioniert nicht. Mit dem Text passiert nichts.
Lizarisk

Der von NLTK angenommene Workflow besteht darin, dass Sie zuerst in Sätze und dann jeden Satz in Wörter umwandeln. Deshalb word_tokenize()funktioniert es nicht mit mehreren Sätzen. Um die Interpunktion zu entfernen, können Sie einen regulären Ausdruck oder die Python- isalnum()Funktion verwenden.
Suzana

2
Es funktioniert : >>> 'with dot.'.translate(None, string.punctuation) 'with dot'(Beachten Sie keinen Punkt am Ende des Ergebnisses) Es kann Probleme verursachen, wenn Sie Dinge wie 'end of sentence.No space'haben. In diesem Fall tun Sie dies stattdessen: Dies the_text.translate(string.maketrans(string.punctuation, ' '*len(string.punctuation)))ersetzt alle Interpunktion durch Leerzeichen.
Bakuriu

Hoppla, es funktioniert zwar, aber nicht mit Unicode-Zeichenfolgen.
Lizarisk

Antworten:


162

Schauen Sie sich die anderen Tokenisierungsoptionen an, die nltk hier bietet . Sie können beispielsweise einen Tokenizer definieren, der Sequenzen alphanumerischer Zeichen als Token auswählt und alles andere löscht:

from nltk.tokenize import RegexpTokenizer

tokenizer = RegexpTokenizer(r'\w+')
tokenizer.tokenize('Eighty-seven miles to go, yet.  Onward!')

Ausgabe:

['Eighty', 'seven', 'miles', 'to', 'go', 'yet', 'Onward']

55
Beachten Sie, dass Sie bei Verwendung dieser Option Funktionen in natürlicher Sprache verlieren, die speziell für das word_tokenizeAufteilen von Kontraktionen gelten. Sie können die Regex naiv aufteilen, \w+ohne dass die NLTK erforderlich ist.
sffc

3
Um den @ sffc-Kommentar zu veranschaulichen, verlieren Sie möglicherweise Wörter wie "Mr."
Geekazoid

es ersetzt 'n't' durch 't', wie man das loswird?
Md. Ashikur Rahman

46

Sie benötigen NLTK nicht wirklich, um Interpunktion zu entfernen. Sie können es mit einfachem Python entfernen. Für Saiten:

import string
s = '... some string with punctuation ...'
s = s.translate(None, string.punctuation)

Oder für Unicode:

import string
translate_table = dict((ord(char), None) for char in string.punctuation)   
s.translate(translate_table)

und verwenden Sie diese Zeichenfolge dann in Ihrem Tokenizer.

Das PS- String-Modul verfügt über einige andere Sätze von Elementen, die entfernt werden können (z. B. Ziffern).


3
Entfernen Sie alle Satzzeichen mit dem Listenausdruck, der auch funktioniert. a = "*fa,fd.1lk#$" print("".join([w for w in a if w not in string.punctuation]))
Johnny Zhang

32

Der folgende Code entfernt alle Satzzeichen sowie nicht alphabetische Zeichen. Aus ihrem Buch kopiert.

http://www.nltk.org/book/ch01.html

import nltk

s = "I can't do this now, because I'm so tired.  Please give me some time. @ sd  4 232"

words = nltk.word_tokenize(s)

words=[word.lower() for word in words if word.isalpha()]

print(words)

Ausgabe

['i', 'ca', 'do', 'this', 'now', 'because', 'i', 'so', 'tired', 'please', 'give', 'me', 'some', 'time', 'sd']

17
Beachten Sie jedoch, dass Sie mit dieser Methode das Wort "nicht" in Fällen wie "nicht" oder "nicht" verlieren, was für das Verständnis und die Klassifizierung des Satzes sehr wichtig sein kann. Es ist besser, satz.translate (string.maketrans ("", "",), chars_to_remove) zu verwenden, wobei chars_to_remove "., ':;!?" Sein kann.
MikeL

3
@MikeL Sie können Wörter wie "kann nicht" und "nicht" nicht umgehen, indem Sie Kontraktionen und Kontraktionen.fix (satz_hier) importieren, bevor Sie tokanisieren. Es wird "kann nicht" in "kann nicht" und "nicht" in "nicht" verwandeln.
Zipline86

16

Wie in Kommentaren bemerkt, beginnen Sie mit sent_tokenize (), da word_tokenize () nur für einen einzelnen Satz funktioniert. Sie können Interpunktion mit filter () herausfiltern. Und wenn Sie Unicode-Zeichenfolgen haben, stellen Sie sicher, dass es sich um ein Unicode-Objekt handelt (kein 'str', das mit einer Codierung wie 'utf-8' codiert ist).

from nltk.tokenize import word_tokenize, sent_tokenize

text = '''It is a blue, small, and extraordinary ball. Like no other'''
tokens = [word for sent in sent_tokenize(text) for word in word_tokenize(sent)]
print filter(lambda word: word not in ',-', tokens)

14
Der größte Teil der Komplexität des Penn Treebank-Tokenizers hängt mit dem richtigen Umgang mit Interpunktion zusammen. Warum sollten Sie einen teuren Tokenizer verwenden, der die Interpunktion gut handhabt, wenn Sie nur die Interpunktion entfernen möchten?
Rmalouf

3
word_tokenizeist eine Funktion, die zurückgibt [token for sent in sent_tokenize(text, language) for token in _treebank_word_tokenize(sent)]. Ich denke also, dass Ihre Antwort das tut, was nltk bereits tut: Verwenden sent_tokenize()vor Verwenden word_tokenize(). Zumindest ist dies für nltk3.
Kurt Bourbaki

2
@rmalouf, weil Sie keine Interpunktions-Token benötigen? Also willst du didund n'taber nicht.
Ciprian Tomoiagă

11

Ich habe gerade den folgenden Code verwendet, mit dem alle Satzzeichen entfernt wurden:

tokens = nltk.wordpunct_tokenize(raw)

type(tokens)

text = nltk.Text(tokens)

type(text)  

words = [w.lower() for w in text if w.isalpha()]

2
Warum Token in Text konvertieren?
Sadik

6

Ich denke, Sie brauchen eine Art Matching für reguläre Ausdrücke (der folgende Code ist in Python 3):

import string
import re
import nltk

s = "I can't do this now, because I'm so tired.  Please give me some time."
l = nltk.word_tokenize(s)
ll = [x for x in l if not re.fullmatch('[' + string.punctuation + ']+', x)]
print(l)
print(ll)

Ausgabe:

['I', 'ca', "n't", 'do', 'this', 'now', ',', 'because', 'I', "'m", 'so', 'tired', '.', 'Please', 'give', 'me', 'some', 'time', '.']
['I', 'ca', "n't", 'do', 'this', 'now', 'because', 'I', "'m", 'so', 'tired', 'Please', 'give', 'me', 'some', 'time']

Sollte in den meisten Fällen gut funktionieren, da Interpunktion entfernt wird, während Token wie "n't" erhalten bleiben, die von Regex-Tokenizern wie z wordpunct_tokenize.


Dies wird auch Dinge wie ...und --unter Beibehaltung von Kontraktionen entfernen , was s.translate(None, string.punctuation)nicht der
Fall ist

5

Mit freundlichen Grüßen fragen, was ist ein Wort? Wenn Sie davon ausgehen, dass ein Wort nur aus alphabetischen Zeichen besteht, liegen Sie falsch, da Wörter wie z. B. can'tin Teile (z. B. canund t) zerstört werden, wenn Sie die Interpunktion vor der Tokenisierung entfernen , was sich sehr wahrscheinlich negativ auf Ihr Programm auswirkt.

Daher besteht die Lösung darin, Satzzeichen zu markieren und dann zu entfernen .

import string

from nltk.tokenize import word_tokenize

tokens = word_tokenize("I'm a southern salesman.")
# ['I', "'m", 'a', 'southern', 'salesman', '.']

tokens = list(filter(lambda token: token not in string.punctuation, tokens))
# ['I', "'m", 'a', 'southern', 'salesman']

... und wenn Sie möchten, können Sie bestimmte Token wie z. B. 'mdurch ersetzen am.


4

Ich benutze diesen Code, um Interpunktion zu entfernen:

import nltk
def getTerms(sentences):
    tokens = nltk.word_tokenize(sentences)
    words = [w.lower() for w in tokens if w.isalnum()]
    print tokens
    print words

getTerms("hh, hh3h. wo shi 2 4 A . fdffdf. A&&B ")

Und wenn Sie überprüfen möchten, ob ein Token ein gültiges englisches Wort ist oder nicht, benötigen Sie möglicherweise PyEnchant

Lernprogramm:

 import enchant
 d = enchant.Dict("en_US")
 d.check("Hello")
 d.check("Helo")
 d.suggest("Helo")

2
Beachten Sie, dass diese Lösung Kontraktionen abtötet. Das liegt daran, word_tokenizedass Sie den Standard-Tokenizer verwenden, der TreebankWordTokenizerKontraktionen aufteilt (z. B. can'tnach ( ca, n't). Ist n'tjedoch nicht alphanumerisch und geht dabei verloren.
Diego Ferri

1

Interpunktion entfernen (Es wird entfernt. Sowie Teil der Interpunktionsbehandlung mit dem folgenden Code)

        tbl = dict.fromkeys(i for i in range(sys.maxunicode) if unicodedata.category(chr(i)).startswith('P'))
        text_string = text_string.translate(tbl) #text_string don't have punctuation
        w = word_tokenize(text_string)  #now tokenize the string 

Beispieleingabe / -ausgabe:

direct flat in oberoi esquire. 3 bhk 2195 saleable 1330 carpet. rate of 14500 final plus 1% floor rise. tax approx 9% only. flat cost with parking 3.89 cr plus taxes plus possession charger. middle floor. north door. arey and oberoi woods facing. 53% paymemt due. 1% transfer charge with buyer. total cost around 4.20 cr approx plus possession charges. rahul soni

['direct', 'flat', 'oberoi', 'esquire', '3', 'bhk', '2195', 'saleable', '1330', 'carpet', 'rate', '14500', 'final', 'plus', '1', 'floor', 'rise', 'tax', 'approx', '9', 'flat', 'cost', 'parking', '389', 'cr', 'plus', 'taxes', 'plus', 'possession', 'charger', 'middle', 'floor', 'north', 'door', 'arey', 'oberoi', 'woods', 'facing', '53', 'paymemt', 'due', '1', 'transfer', 'charge', 'buyer', 'total', 'cost', 'around', '420', 'cr', 'approx', 'plus', 'possession', 'charges', 'rahul', 'soni']


Vielen Dank

1

Wenn Sie nur @rmalouf zur Lösung hinzufügen, enthält dies keine Zahlen, da \ w + [a-zA-Z0-9_] entspricht.

from nltk.tokenize import RegexpTokenizer
tokenizer = RegexpTokenizer(r'[a-zA-Z]')
tokenizer.tokenize('Eighty-seven miles to go, yet.  Onward!')

Dieser erstellt einen Token für jeden Buchstaben.
Rishabh Gupta

1

Sie können dies in einer Zeile ohne nltk (Python 3.x) tun.

import string
string_text= string_text.translate(str.maketrans('','',string.punctuation))
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.