Bagaimana cara menghilangkan tanda baca menggunakan NLTK tokenizer?

125

Saya baru mulai menggunakan NLTK dan saya tidak begitu mengerti bagaimana cara mendapatkan daftar kata dari teks. Jika saya menggunakan nltk.word_tokenize(), saya mendapatkan daftar kata dan tanda baca. Saya hanya membutuhkan kata-kata saja. Bagaimana cara menghilangkan tanda baca? Juga word_tokenizetidak berfungsi dengan beberapa kalimat: titik ditambahkan ke kata terakhir.

lizarisk
sumber
12
Mengapa Anda tidak menghapus sendiri tanda baca tersebut? nltk.word_tokenize(the_text.translate(None, string.punctuation))harus bekerja di python2 sedangkan di python3 Anda bisa melakukannya nltk.work_tokenize(the_text.translate(dict.fromkeys(string.punctuation))).
Bakuriu
3
Ini tidak berhasil. Tidak ada yang terjadi dengan teks.
lizarisk
Alur kerja yang diasumsikan oleh NLTK adalah Anda pertama kali membuat token menjadi kalimat dan kemudian setiap kalimat menjadi kata-kata. Itulah mengapa word_tokenize()tidak bekerja dengan banyak kalimat. Untuk menghilangkan tanda baca, Anda dapat menggunakan ekspresi reguler atau isalnum()fungsi python .
Suzana
2
Ini tidak bekerja: >>> 'with dot.'.translate(None, string.punctuation) 'with dot'(catatan tidak ada dot pada akhir hasil) itu dapat menyebabkan masalah jika Anda memiliki hal-hal seperti 'end of sentence.No space', dalam hal melakukan ini sebagai gantinya: the_text.translate(string.maketrans(string.punctuation, ' '*len(string.punctuation)))yang menggantikan semua tanda baca dengan spasi putih.
Bakuriu
Ups, ini memang berfungsi, tetapi tidak dengan string Unicode.
lizarisk

Jawaban:

162

Lihat opsi tokenisasi lain yang disediakan nltk di sini . Misalnya, Anda dapat menentukan tokenizer yang memilih urutan karakter alfanumerik sebagai token dan menghapus yang lainnya:

from nltk.tokenize import RegexpTokenizer

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

Keluaran:

['Eighty', 'seven', 'miles', 'to', 'go', 'yet', 'Onward']
rmalouf.dll
sumber
55
Perhatikan bahwa jika Anda menggunakan opsi ini, Anda kehilangan fitur bahasa alami yang khusus word_tokenizeseperti memisahkan kontraksi. Anda dapat membagi regex secara naif \w+tanpa perlu NLTK.
sffc
3
Untuk mengilustrasikan komentar @sffc, Anda mungkin kehilangan kata-kata seperti "Mr."
geekazoid
itu menggantikan 'n't' menjadi 't' bagaimana cara menyingkirkan ini?
Md. Ashikur Rahman
46

Anda tidak benar-benar membutuhkan NLTK untuk menghapus tanda baca. Anda dapat menghapusnya dengan python sederhana. Untuk string:

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

Atau untuk unicode:

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

dan kemudian gunakan string ini di tokenizer Anda.

Modul string PS memiliki beberapa set elemen lain yang dapat dihapus (seperti digit).

Salvador Dali
sumber
3
Hapus semua tanda baca menggunakan ekspresi daftar yang juga berfungsi. a = "*fa,fd.1lk#$" print("".join([w for w in a if w not in string.punctuation]))
Johnny Zhang
32

Kode di bawah ini akan menghapus semua tanda baca serta karakter non abjad. Disalin dari buku mereka.

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)

keluaran

['i', 'ca', 'do', 'this', 'now', 'because', 'i', 'so', 'tired', 'please', 'give', 'me', 'some', 'time', 'sd']
Madura Pradeep
sumber
17
Perlu diketahui bahwa dengan menggunakan metode ini, Anda akan kehilangan kata "tidak" dalam kasus seperti "tidak bisa" atau "tidak", yang mungkin sangat penting untuk memahami dan mengklasifikasikan kalimat. Lebih baik menggunakan kalimat.translate (string.maketrans ("", "",), chars_to_remove), di mana chars_to_remove bisa "., ':;!?"
MikeL
3
@MikeL Anda tidak dapat menghindari kata-kata seperti "tidak bisa" dan "tidak" dengan import contractions and contractions.fix (kalimat_di sini) sebelum melakukan tokanizing. Ini akan mengubah "tidak bisa" menjadi "tidak bisa" dan "jangan" menjadi "jangan".
zipline86
16

Seperti yang terlihat di komentar dimulai dengan sent_tokenize (), karena word_tokenize () hanya berfungsi pada satu kalimat. Anda dapat memfilter tanda baca dengan filter (). Dan jika Anda memiliki string unicode, pastikan itu adalah objek unicode (bukan 'str' yang dikodekan dengan beberapa pengkodean seperti 'utf-8').

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)
palooh
sumber
14
Sebagian besar kerumitan yang terlibat dalam Penn Treebank tokenizer berkaitan dengan penanganan tanda baca yang tepat. Mengapa menggunakan tokenizer mahal yang menangani tanda baca dengan baik jika Anda hanya akan menghapus tanda baca?
rmalouf
3
word_tokenizeadalah fungsi yang mengembalikan [token for sent in sent_tokenize(text, language) for token in _treebank_word_tokenize(sent)]. Jadi saya pikir jawaban Anda adalah melakukan apa yang sudah dilakukan nltk: menggunakan sent_tokenize()sebelum menggunakan word_tokenize(). Setidaknya ini untuk nltk3.
Kurt Bourbaki
2
@rmalouf karena Anda tidak memerlukan token khusus tanda baca? Jadi Anda ingin diddan n'ttetapi tidak.
Ciprian Tomoiagă
11

Saya baru saja menggunakan kode berikut, yang menghapus semua tanda baca:

tokens = nltk.wordpunct_tokenize(raw)

type(tokens)

text = nltk.Text(tokens)

type(text)  

words = [w.lower() for w in text if w.isalpha()]
vish
sumber
2
mengapa mengonversi token menjadi teks?
Sadik
6

Saya pikir Anda memerlukan semacam pencocokan ekspresi reguler (kode berikut ada di 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)

Keluaran:

['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']

Seharusnya berfungsi dengan baik dalam banyak kasus karena ini menghapus tanda baca sambil mempertahankan token seperti "n't", yang tidak dapat diperoleh dari tokenizers regex seperti wordpunct_tokenize.

Quan Gan
sumber
Ini juga akan menghilangkan hal-hal seperti ...dan --sambil mempertahankan kontraksi, yang s.translate(None, string.punctuation)tidak akan
CJ Jackson
5

Dengan tulus bertanya, apa itu kata? Jika asumsi Anda adalah bahwa sebuah kata hanya terdiri dari karakter abjad, Anda salah karena kata-kata seperti can'takan dihancurkan menjadi beberapa bagian (seperti candan t) jika Anda menghapus tanda baca sebelum tokenisasi , yang sangat mungkin mempengaruhi program Anda secara negatif.

Karenanya, solusinya adalah dengan melakukan tokenisasi dan kemudian menghapus token tanda baca .

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']

... dan kemudian jika Anda mau, Anda dapat mengganti token tertentu seperti 'mdengan am.

Bora M. Alper
sumber
4

Saya menggunakan kode ini untuk menghapus tanda baca:

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 ")

Dan jika Anda ingin memeriksa apakah token adalah kata bahasa Inggris yang valid atau tidak, Anda mungkin memerlukan PyEnchant

Tutorial:

 import enchant
 d = enchant.Dict("en_US")
 d.check("Hello")
 d.check("Helo")
 d.suggest("Helo")
zhenv5
sumber
2
Berhati-hatilah karena larutan ini membunuh kontraksi. Itu karena word_tokenizemenggunakan tokenizer standar TreebankWordTokenizer,, yang membagi kontraksi (misalnya can'tke ( ca, n't). Namun n'tbukan alfanumerik dan tersesat dalam prosesnya.
Diego Ferri
1

Hapus tanda baca (Ini akan menghapus. Serta bagian dari penanganan tanda baca menggunakan kode di bawah ini)

        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 

Contoh Masukan / Keluaran:

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']

ascii_walker
sumber
Terima kasih banyak
1

Hanya menambahkan solusi dengan @rmalouf, ini tidak akan menyertakan angka apa pun karena \ w + sama dengan [a-zA-Z0-9_]

from nltk.tokenize import RegexpTokenizer
tokenizer = RegexpTokenizer(r'[a-zA-Z]')
tokenizer.tokenize('Eighty-seven miles to go, yet.  Onward!')
Himanshu Aggarwal
sumber
Yang ini membuat satu token untuk setiap huruf.
Rishabh Gupta
1

Anda dapat melakukannya dalam satu baris tanpa nltk (python 3.x).

import string
string_text= string_text.translate(str.maketrans('','',string.punctuation))
Nishān Wickramarathna
sumber