Как удалить специальные символы списка ("()", "'", ",") из вывода би / триграммы в Python - PullRequest
0 голосов
/ 30 августа 2018

Я написал код, который вычисляет частоту биграмм / триграмм из текстового ввода, используя NLTK. Проблема, с которой я здесь сталкиваюсь, заключается в том, что, поскольку выходные данные получены в виде списка Python, мой вывод содержит специфичные для списка символы, т. Е. ("()", "'", ","). Я планирую экспортировать это в CSV-файл, и поэтому я хотел бы удалить эти специальные символы на самом уровне кода. Как я могу сделать это редактирование.

Введите код:

import nltk
from nltk import word_tokenize, pos_tag
from nltk.collocations import *
from itertools import *
from nltk.util import ngrams
from nltk.corpus import stopwords

corpus = '''The pure amnesia of her face,
newborn. I looked so far into her that, for a while, looked so far into her that, for a while  looked so far into her that, for a while looked so far into her that, for a while the visual 
held no memory. Little by little, I returned to myself, waking to nurse the visual held no  memory. Little by little, I returned to myself, waking to nurse
'''
s_corpus = corpus.lower()

stop_words = set(stopwords.words('english'))

tokens = nltk.word_tokenize(s_corpus)
tokens = [word for word in tokens if word not in stop_words]

c_tokens = [''.join(e for e in string if e.isalnum()) for string in tokens]
c_tokens = [x for x in c_tokens if x]

bgs_2 = nltk.bigrams(c_tokens)
bgs_3 = nltk.trigrams(c_tokens)

fdist = nltk.FreqDist(bgs_3)

tmp = list()
for k,v in fdist.items():
    tmp.append((v,k))
tmp = sorted (tmp, reverse=True)

for kk,vv in tmp[:]:
    print (vv,kk)

Токовый выход:

('looked', 'far', 'looked') 3
('far', 'looked', 'far') 3
('visual', 'held', 'memory') 2
('returned', 'waking', 'nurse') 2

Ожидаемый результат:

looked far looked, 3
far looked far, 3
visual held memory, 2
returned waking nurse, 2

Заранее спасибо за помощь.

Ответы [ 2 ]

0 голосов
/ 31 августа 2018

Лучший вопрос был бы что это за ("()", "'",",") в выводе ngram?

>>> from nltk import ngrams
>>> from nltk import word_tokenize

# Split a sentence into a list of "words"
>>> word_tokenize("This is a foo bar sentence")
['This', 'is', 'a', 'foo', 'bar', 'sentence']
>>> type(word_tokenize("This is a foo bar sentence"))
<class 'list'>

# Extract bigrams.
>>> list(ngrams(word_tokenize("This is a foo bar sentence"), 2))
[('This', 'is'), ('is', 'a'), ('a', 'foo'), ('foo', 'bar'), ('bar', 'sentence')]

# Okay, so the output is a list, no surprise.
>>> type(list(ngrams(word_tokenize("This is a foo bar sentence"), 2)))
<class 'list'>

Но какой тип ('This', 'is')?

>>> list(ngrams(word_tokenize("This is a foo bar sentence"), 2))[0]
('This', 'is')
>>> first_thing_in_output = list(ngrams(word_tokenize("This is a foo bar sentence"), 2))[0]
>>> type(first_thing_in_output)
<class 'tuple'>

Ах, это кортеж, см. https://realpython.com/python-lists-tuples/

Что происходит при печати кортежа?

>>> print(first_thing_in_output)
('This', 'is')

Что произойдет, если вы преобразуете их в str()?

>>> print(str(first_thing_in_output))
('This', 'is')

Но Мне нужен вывод This is вместо ('This', 'is'), поэтому я буду использовать функцию str.join(), см. https://www.geeksforgeeks.org/join-function-python/:

>>> print(' '.join((first_thing_in_output)))
This is

Теперь это хороший момент, чтобы действительно пройти учебник по базовым типам Python , чтобы понять, что происходит. Кроме того, было бы хорошо понять, как работают «контейнерные» типы, например, https://github.com/usaarhat/pywarmups/blob/master/session2.md


Проходя через оригинальный пост, с кодом довольно много проблем.

Полагаю, цель кода:

  • Токенизация текста и удаление стоп-слов
  • Извлечение нграмм (без стоп-слов)
  • Распечатайте их строковые формы и их количество

Сложная часть: stopwords.words('english') не содержит знаков препинания, так что в итоге вы получите странные нграммы с пунктуацией:

from nltk import word_tokenize
from nltk.util import ngrams
from nltk.corpus import stopwords

text = '''The pure amnesia of her face,
newborn. I looked so far into her that, for a while, looked so far into her that, for a while  looked so far into her that, for a while looked so far into her that, for a while the visual 
held no memory. Little by little, I returned to myself, waking to nurse the visual held no  memory. Little by little, I returned to myself, waking to nurse
'''

stoplist = set(stopwords.words('english'))

tokens = [token for token in nltk.word_tokenize(text) if token not in stoplist]

list(ngrams(tokens, 2))

[выход]:

[('The', 'pure'),
 ('pure', 'amnesia'),
 ('amnesia', 'face'),
 ('face', ','),
 (',', 'newborn'),
 ('newborn', '.'),
 ('.', 'I'),
 ('I', 'looked'),
 ('looked', 'far'),
 ('far', ','),
 (',', ','), ...]

Возможно, вы хотели бы дополнить стоп-лист пунктуацией, например,

from string import punctuation
from nltk import word_tokenize
from nltk.util import ngrams
from nltk.corpus import stopwords

text = '''The pure amnesia of her face,
newborn. I looked so far into her that, for a while, looked so far into her that, for a while  looked so far into her that, for a while looked so far into her that, for a while the visual 
held no memory. Little by little, I returned to myself, waking to nurse the visual held no  memory. Little by little, I returned to myself, waking to nurse
'''

stoplist = set(stopwords.words('english') + list(punctuation))

tokens = [token for token in nltk.word_tokenize(text) if token not in stoplist]

list(ngrams(tokens, 2))

[выход]:

[('The', 'pure'),
 ('pure', 'amnesia'),
 ('amnesia', 'face'),
 ('face', 'newborn'),
 ('newborn', 'I'),
 ('I', 'looked'),
 ('looked', 'far'),
 ('far', 'looked'),
 ('looked', 'far'), ...]

Тогда вы поняли, что токены типа I должны быть стоп-словом, но все еще существуют в вашем списке нграмм. Это потому, что список из stopwords.words('english') в нижнем регистре, например

>>> stopwords.words('english')

[вне]:

['i',
 'me',
 'my',
 'myself',
 'we',
 'our',
 'ours',
 'ourselves',
 'you',
 "you're", ...]

Поэтому, когда вы проверяете, есть ли токен в стоп-листе, вы должны также нижний регистр. ( Избегайте в нижнем регистре предложения до word_tokenize, потому что word_tokenize может получить подсказки от заглавных букв). Таким образом:

from string import punctuation
from nltk import word_tokenize
from nltk.util import ngrams
from nltk.corpus import stopwords

text = '''The pure amnesia of her face,
newborn. I looked so far into her that, for a while, looked so far into her that, for a while  looked so far into her that, for a while looked so far into her that, for a while the visual 
held no memory. Little by little, I returned to myself, waking to nurse the visual held no  memory. Little by little, I returned to myself, waking to nurse
'''

stoplist = set(stopwords.words('english') + list(punctuation))

tokens = [token for token in nltk.word_tokenize(text) if token.lower() not in stoplist]

list(ngrams(tokens, 2))

[выход]:

[('pure', 'amnesia'),
 ('amnesia', 'face'),
 ('face', 'newborn'),
 ('newborn', 'looked'),
 ('looked', 'far'),
 ('far', 'looked'),
 ('looked', 'far'),
 ('far', 'looked'),
 ('looked', 'far'),
 ('far', 'looked'), ...]

Теперь нграммы выглядят так, как будто достигают целей:

  • Токенизация текста и удаление стоп-слов
  • Извлечение нграмм (без стоп-слов)

Затем в последней части, где вы хотите распечатать нграммы в файл в отсортированном порядке, вы можете использовать Freqdist.most_common(), который будет отображаться в порядке убывания, например,

from string import punctuation
from nltk import word_tokenize
from nltk.util import ngrams
from nltk.corpus import stopwords
from nltk import FreqDist

text = '''The pure amnesia of her face,
newborn. I looked so far into her that, for a while, looked so far into her that, for a while  looked so far into her that, for a while looked so far into her that, for a while the visual 
held no memory. Little by little, I returned to myself, waking to nurse the visual held no  memory. Little by little, I returned to myself, waking to nurse
'''

stoplist = set(stopwords.words('english') + list(punctuation))

tokens = [token for token in nltk.word_tokenize(text) if token.lower() not in stoplist]

FreqDist(ngrams(tokens, 2)).most_common()

[выход]:

[(('looked', 'far'), 4),
 (('far', 'looked'), 3),
 (('visual', 'held'), 2),
 (('held', 'memory'), 2),
 (('memory', 'Little'), 2),
 (('Little', 'little'), 2),
 (('little', 'returned'), 2),
 (('returned', 'waking'), 2),
 (('waking', 'nurse'), 2),
 (('pure', 'amnesia'), 1),
 (('amnesia', 'face'), 1),
 (('face', 'newborn'), 1),
 (('newborn', 'looked'), 1),
 (('far', 'visual'), 1),
 (('nurse', 'visual'), 1)]

(См. Также: Разница между коллекциями Python.Counter и nltk.probability.FreqDist )

Наконец, наконец, распечатывая это в файл, вы действительно должны использовать контекстный менеджер, http://eigenhombre.com/introduction-to-context-managers-in-python.html

with open('bigrams-list.tsv', 'w') as fout:
    for bg, count in FreqDist(ngrams(tokens, 2)).most_common():
        print('\t'.join([' '.join(bg), str(count)]), end='\n', file=fout)

[биграммы-list.tsv]:

looked far  4
far looked  3
visual held 2
held memory 2
memory Little   2
Little little   2
little returned 2
returned waking 2
waking nurse    2
pure amnesia    1
amnesia face    1
face newborn    1
newborn looked  1
far visual  1
nurse visual    1

Пища для размышлений

Теперь вы видите этот странный биграмм Little little, имеет ли смысл?

Это побочный продукт удаления by из

Мало-помалу

Так что теперь, в зависимости от того, что является конечной задачей для извлеченных вами ngram, вы, возможно, на самом деле не захотите удалять стоп-слова из списка.

0 голосов
/ 30 августа 2018

Так что просто, чтобы «исправить» ваш вывод: Используйте это, чтобы напечатать ваши данные:

for kk,vv in tmp:
    print(" ".join(list(kk)),",%d" % vv)

НО если вы собираетесь анализировать это в CSV, вы должны собрать свои выходные данные в другом формате.

В настоящее время вы создаете список кортежей, в котором указан номер и номер. попробуйте собрать ваши данные в виде списка списков, содержащих каждое значение. Таким образом, вы можете просто записать его прямо в CSV-файл.

Посмотрите здесь: Создайте файл .csv со значениями из списка Python

...