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

the*_*ern 8 python text stemming plural singular

我有txt文件,如下所示:

word, 23
Words, 2
test, 1
tests, 4
Run Code Online (Sandbox Code Playgroud)

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

word, 23
word, 2
test, 1
test, 4
Run Code Online (Sandbox Code Playgroud)

我希望能够在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)))
Run Code Online (Sandbox Code Playgroud)

我也尝试过这两个定义而不是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
Run Code Online (Sandbox Code Playgroud)

之后我想重复单词(例如testtest)并通过将它们旁边的数字相加来合并它们.例如:

word, 25
test, 5
Run Code Online (Sandbox Code Playgroud)

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

小智 15

如果你有单词复杂的单词,我不建议你使用词干,但一个适当的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
Run Code Online (Sandbox Code Playgroud)

收益:

>>> ['caress', 'fly', 'dy', 'mule', 'goose', 'mouse', 'bar', 'foo', 'foo', 'family', 'family', 'dog', 'dog', 'child', 'wolf']
Run Code Online (Sandbox Code Playgroud)

它并不完美,但它是我发现的最好的.96%基于文档:http://www.clips.ua.ac.be/pages/pattern-en#pluralization

  • `inflect` 包更容易安装 /sf/answers/1531100301/ (3认同)
  • 似乎`pattern`包仅适用于`Python 2.*`:'Python 3版本目前仅在开发分支上可用' (2认同)
  • @Chowlett2 你通常是正确的。安装这两个软件包的过程是相同的。(`pip 安装`)。但是,我遇到了“模式”依赖性的问题。我手头没有示例,但“pip install pattern”安装了 39 个包。`pip install inflect` 仅安装 1。 (2认同)

NBa*_*ley 8

看起来你对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
Run Code Online (Sandbox Code Playgroud)

这很好,但是当你想将结果传递给stem()时,它将是一个大字符串,而不是一个单词列表.这意味着当您遍历输入时for word in a,您将遍历输入字符串的每个单独字符并将stemmer应用于这些单个字符.

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

这绝对不适用于您的目的,我们可以做一些不同的事情.

  1. 我们可以更改它,以便我们将输入文件作为一个行列表读取
  2. 我们可以使用大字符串并将其分解为一个列表.
  3. 我们可以一次一个地查看行列表中的每一行.

为了方便起见,让我们滚动#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
Run Code Online (Sandbox Code Playgroud)

这应该给我们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
Run Code Online (Sandbox Code Playgroud)

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

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)))
Run Code Online (Sandbox Code Playgroud)

当我有以下input.txt

soc, 32
socs, 1
dogs, 8
Run Code Online (Sandbox Code Playgroud)

我得到以下标准输出:

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
Run Code Online (Sandbox Code Playgroud)

input.txt看起来像这样:

soc, 32
soc, 1
dog, 8
Run Code Online (Sandbox Code Playgroud)

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