使用Python将复数转换为文本文件中的单数

时间:2015-07-13 15:50:49

标签: python text stemming plural singular

我有txt文件,如下所示:

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

我希望他们看起来像这样:

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

我希望能够在Python中获取一个txt文件并将多个单词转换为单数。这是我的代码:

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

我也尝试过这两个定义而不是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

之后,我想要重复一句话(例如testtest),然后将它们旁边的数字相加合并。例如:

word, 25
test, 5

我不知道该怎么做。解决方案很好但不是必需的。

3 个答案:

答案 0 :(得分:13)

如果你有单词复杂的单词,我不建议你使用词干但是一个合适的python包链接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 :(得分:6)

您似乎对Python非常熟悉,但我仍然会尝试解释一些步骤。让我们从第一个对文字进行淡化的问题开始。当您使用a.read()读入多行文件(在您的情况下为单词,数字csv)时,您将要将整个文件读取为一个大字符串。

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

这很好,但是当你想把结果传递给stem()时,它将是一个大字符串,而不是一个单词列表。这意味着当您使用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. 我们可以使用大字符串并将其分解为列表。
  4. 我们可以一次一个地检查一行中的每一行。
  5. 为了方便起见,让我们滚动#1。这将需要将openfile(f)更改为以下内容:

    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
    

    这应该给我们b作为一个行列表,即[' soc,32',' soc,1',...]。因此,当我们将字符串列表传递给stem()时,下一个问题就变成了我们如何处理字符串列表。一种方法如下:

    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
    

    这绝对是一个非常粗略的解决方案,但是应该充分迭代输入中的所有行,并对它们进行分解。这很粗糙,因为当你放大它时,分裂弦并重新组装它们并不是特别快。但是,如果您对此感到满意,那么剩下的就是遍历新行列表,并将它们写入您的文件。根据我的经验,写入新文件通常更安全,但这应该可以正常工作。

    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
    

    关于将数字与相同单词合并的第二个问题从上面改变了我们的解决方案。根据评论中的建议,您应该看一下使用词典来解决这个问题。而不是将其作为一个大的列表,更好(也可能更pythonic)的方法是迭代输入的每一行,并在处理它们时阻止它们。如果您仍在努力解决这个问题,我会稍微编写一下这方面的代码。

答案 2 :(得分:2)

Nodebox英语语言学库包含用于将复数形式转换为单一形式的脚本,反之亦然。结帐教程: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