2015-07-13 3 views
4

У меня есть текстовые файлы, которые выглядят следующим образом:Преобразование множественного числа в единственном числе в виде текстового файла с Python

word, 23 
Words, 2 
test, 1 
tests, 4 

И я хочу, чтобы выглядеть следующим образом:

word, 23 
word, 2 
test, 1 
test, 4 

Я хочу, чтобы иметь возможность взять txt-файл в Python и преобразовать множественные слова в сингулярные. Вот мой код:

import nltk 

f = raw_input("Please enter a filename: ") 

def openfile(f): 
    with open(f,'r') as a: 
     a = a.read() 
     a = a.lower() 
     return a 

def stem(a): 
    p = nltk.PorterStemmer() 
    [p.stem(word) for word in a] 
    return a 

def returnfile(f, a): 
    with open(f,'w') as d: 
     d = d.write(a) 
    #d.close() 

print openfile(f) 
print stem(openfile(f)) 
print returnfile(f, stem(openfile(f))) 

Я также пробовал эти 2 определения вместо stem определения:

def singular(a): 
    for line in a: 
     line = line[0] 
     line = str(line) 
     stemmer = nltk.PorterStemmer() 
     line = stemmer.stem(line) 
     return line 

def stem(a): 
    for word in a: 
     for suffix in ['s']: 
      if word.endswith(suffix): 
       return word[:-len(suffix)] 
      return word 

После этого я хотел бы взять повторяющиеся слова (например, test и test) и объединить их добавляя числа рядом с ними. Например:

word, 25 
test, 5 

Я не уверен, как это сделать. Решение было бы неплохо, но не обязательно.

+0

Чтобы попытаться свернуть все значения в одну строку за слово, я рекомендую смотреть вверх [словари в документации] (https: // документы .python.org/2/учебник/datastructures.html # словари). – SuperBiasedMan

+2

Вы хотите сделать что-нибудь с множественными числами, которые не заканчиваются на 's'? то есть. Гуси? Потому что это становится намного сложнее, чем удаление конечных s. Кроме того, как насчет того, когда слово заканчивается на 's', например. 'Класс'. Должен ли ваш скрипт обрабатывать любое слово или есть меньший, более конкретный пул, на который он может нарисовать? – SuperBiasedMan

+0

Нет, я просто хочу удалить s, по крайней мере на данный момент – theintern

ответ

4

Кажется, что вы хорошо знакомы с Python, но я все равно попытаюсь объяснить некоторые из этих шагов. Начнем с первого вопроса о деплюралировании слов. Когда вы читаете в многострочном файле (слово, csv в вашем случае) с помощью a.read(), вы будете читать весь массив файла в одну большую строку.

def openfile(f): 
    with open(f,'r') as a: 
     a = a.read() # a will equal 'soc, 32\nsoc, 1\n...' in your example 
     a = a.lower() 
     return a 

Это хорошо и все, но если вы хотите, чтобы передать результат в стебле(), то это будет как одна большая строка, а не как список слов. Это означает, что когда вы перебираете вход с помощью for word in a, вы будете выполнять итерацию по каждому отдельному символу входной строки и применяя стебельщик к этим индивидуальным символам.

def stem(a): 
    p = nltk.PorterStemmer() 
    a = [p.stem(word) for word in a] # ['s', 'o', 'c', ',', ' ', '3', '2', '\n', ...] 
    return a 

Это определенно не работает для ваших целей, и мы можем сделать несколько разных вещей.

  1. Мы можем изменить его так, что мы читаем входной файл в виде одного списка линий
  2. Мы можем использовать большую строку и разбить его в список самого.
  3. Мы можем проходить через каждую строку в списке строк по одному за раз.

Для удобства, давайте катимся с №1. Это потребует изменения OpenFile (е) следующим образом:

def openfile(f): 
    with open(f,'r') as a: 
     a = a.readlines() # a will equal 'soc, 32\nsoc, 1\n...' in your example 
     b = [x.lower() for x in a] 
     return b 

Это должно дать нам б как список строк, то есть [ 'Soc, 32', 'Soc, 1', ...]. Таким образом, следующая проблема становится тем, что мы делаем со списком строк, когда мы передаем ее стеку(). Один из способов заключается в следующем:

def stem(a): 
    p = nltk.PorterStemmer() 
    b = [] 
    for line in a: 
     split_line = line.split(',') #break it up so we can get access to the word 
     new_line = str(p.stem(split_line[0])) + ',' + split_line[1] #put it back together 
     b.append(new_line) #add it to the new list of lines 
    return b 

Это, безусловно, довольно грубое решение, но должны адекватно перебрать все строки в вашем входе и depluralize их. Это грубо, потому что разделение строк и их повторная сборка не особенно быстро, когда вы масштабируете его. Однако, если вас это устраивает, все, что осталось, это перебрать список новых строк и записать их в ваш файл. По моему опыту, обычно безопаснее писать в новый файл, но это должно работать нормально.

def returnfile(f, a): 
    with open(f,'w') as d: 
     for line in a: 
      d.write(line) 


print openfile(f) 
print stem(openfile(f)) 
print returnfile(f, stem(openfile(f))) 

Когда у меня есть следующий input.txt

soc, 32 
socs, 1 
dogs, 8 

я получаю стандартный вывод:

Please enter a filename: input.txt 
['soc, 32\n', 'socs, 1\n', 'dogs, 8\n'] 
['soc, 32\n', 'soc, 1\n', 'dog, 8\n'] 
None 

И input.txt выглядит следующим образом:

soc, 32 
soc, 1 
dog, 8 

Второй вопрос, связанный с объединением чисел с теми же словами, изменяет наше решение сверху. Согласно предложению в комментариях, вы должны взглянуть на использование словарей, чтобы решить эту проблему. Вместо того, чтобы делать все это как один большой список, лучший (и, вероятно, более пуфонический) способ сделать это состоит в том, чтобы перебирать каждую строку вашего ввода и прерывать их при их обработке. Я напишу код об этом немного, если вы все еще работаете, чтобы понять это.

+1

Спасибо вам большое! Это сработало, и я очень ценю помощь! – theintern

6

Если у вас есть сложные слова образовывать форму единственного числа, я не советую вам использовать вытекающие, но пакет ссылку собственно питон pattern:

from pattern.text.en import singularize 

plurals = ['caresses', 'flies', 'dies', 'mules', 'geese', 'mice', 'bars', 'foos', 
      'families', 'dogs', 'child', 'wolves'] 

singles = [singularize(plural) for plural in plurals] 
print singles 

возвращается:

>>> ['caress', 'fly', 'dy', 'mule', 'goose', 'mouse', 'bar', 'foo', 'foo', 'family', 'family', 'dog', 'dog', 'child', 'wolf'] 

Это не идеально, но это лучшее, что я нашел. 96% на основе документов: http://www.clips.ua.ac.be/pages/pattern-en#pluralization

+1

Кажется, что пакет 'pattern' доступен только для' Python 2. * ': 'Версия Python 3 в настоящее время доступна только на ветке разработки' –

+0

Согласно их веб-странице: « Функция uniqueize() возвращает форму множественного числа единственного существительного. Параметр pos (часть речи) может быть установлен как NOUN или ADJECTIVE " Второй параметр функции uniqueize() - pos. –

0

Библиотека английской лингвистики Nodebox содержит скрипты для преобразования множественной формы в одну форму и наоборот. Checkout tutorial: https://www.nodebox.net/code/index.php/Linguistics#pluralization

Чтобы преобразовать множественное число в единственное, просто импортировать модуль singular и использовать функцию singular(). Он обрабатывает соответствующие преобразования слов с разными окончаниями, неправильной формы и т.д.

from en import singular 
print(singular('analyses')) 
print(singular('planetoids')) 
print(singular('children')) 
>>> analysis 
>>> planetoid 
>>> child 
Смежные вопросы