在 python 中完全复制 R 文本预处理

Posted

技术标签:

【中文标题】在 python 中完全复制 R 文本预处理【英文标题】:Exactly replicating R text preprocessing in python 【发布时间】:2014-05-12 21:45:12 【问题描述】:

我想使用 Python 以与在 R 中相同的方式预处理文档语料库。例如,给定一个初始语料库corpus,我希望最终得到一个与使用以下 R 代码生成的:

library(tm)
library(SnowballC)

corpus = tm_map(corpus, tolower)
corpus = tm_map(corpus, removePunctuation)
corpus = tm_map(corpus, removeWords, c("myword", stopwords("english")))
corpus = tm_map(corpus, stemDocument)

是否有一种简单或直接(最好是预先构建)的方法在 Python 中执行此操作?有没有办法确保完全相同的结果?


比如我要预处理

@Apple 耳塞太棒了!我用过的入耳式耳机的最佳声音 曾经有过!

进入

ear pod amaz 有史以来最好的入耳式耳机

【问题讨论】:

在 Python 中使用 nltk 进行自然语言处理。 @ramcdougal:我收集了这么多,但我正在为文档而苦苦挣扎。 看看这个tutorial。它涵盖了标记化、停用词和词干。 @ramcdougal:这是一个好的开始。我缺少的是如何将其应用于大型数据集(例如在 Pandas 数据框中)或在 scikit-learn's CountVectorizer 之类的上下文中使用它,这似乎能够将预处理器作为参数。跨度> 【参考方案1】:

在预处理步骤上让nltktm 之间的东西完全相同似乎很棘手,所以我认为最好的方法是使用rpy2 在R 中运行预处理并将结果拉入python:

import rpy2.robjects as ro
preproc = [x[0] for x in ro.r('''
tweets = read.csv("tweets.csv", stringsAsFactors=FALSE)
library(tm)
library(SnowballC)
corpus = Corpus(VectorSource(tweets$Tweet))
corpus = tm_map(corpus, tolower)
corpus = tm_map(corpus, removePunctuation)
corpus = tm_map(corpus, removeWords, c("apple", stopwords("english")))
corpus = tm_map(corpus, stemDocument)''')]

然后,您可以将其加载到 scikit-learn 中——要使 CountVectorizerDocumentTermMatrix 之间匹配,您唯一需要做的就是删除长度小于 3 的术语:

from sklearn.feature_extraction.text import CountVectorizer
def mytokenizer(x):
    return [y for y in x.split() if len(y) > 2]

# Full document-term matrix
cv = CountVectorizer(tokenizer=mytokenizer)
X = cv.fit_transform(preproc)
X
# <1181x3289 sparse matrix of type '<type 'numpy.int64'>'
#   with 8980 stored elements in Compressed Sparse Column format>

# Sparse terms removed
cv2 = CountVectorizer(tokenizer=mytokenizer, min_df=0.005)
X2 = cv2.fit_transform(preproc)
X2
# <1181x309 sparse matrix of type '<type 'numpy.int64'>'
#   with 4669 stored elements in Compressed Sparse Column format>

让我们用 R 来验证这个匹配:

tweets = read.csv("tweets.csv", stringsAsFactors=FALSE)
library(tm)
library(SnowballC)
corpus = Corpus(VectorSource(tweets$Tweet))
corpus = tm_map(corpus, tolower)
corpus = tm_map(corpus, removePunctuation)
corpus = tm_map(corpus, removeWords, c("apple", stopwords("english")))
corpus = tm_map(corpus, stemDocument)
dtm = DocumentTermMatrix(corpus)
dtm
# A document-term matrix (1181 documents, 3289 terms)
# 
# Non-/sparse entries: 8980/3875329
# Sparsity           : 100%
# Maximal term length: 115 
# Weighting          : term frequency (tf)

sparse = removeSparseTerms(dtm, 0.995)
sparse
# A document-term matrix (1181 documents, 309 terms)
# 
# Non-/sparse entries: 4669/360260
# Sparsity           : 99%
# Maximal term length: 20 
# Weighting          : term frequency (tf)

如您所见,现在两种方法之间存储的元素和术语的数量完全匹配。

【讨论】:

有没有办法将此传递给scikit-learnCountVectorizer 构造函数。文档使它看起来应该是可能的,但我不知道如何。 @raxacoricofallapatorius 更新为包含CountVectorizer。很高兴看到有人在 python 中处理 15.071x 内容! 谢谢。我是 R(我讨厌它)Python(很棒)和分析的新手,所以很难。我希望这门课程是用 Python 教授的! 整个课程团队都对 R 充满热情(这就是我们选择 R 作为课程的原因),但很高兴您找到了适合您的软件包! 在调用removeSparseTerms 之前,3462 将与您的DocumentTermMatrix 中的术语数相匹配。你能用sort(colnames(as.matrix(sparseDTM)))从R中输出排序后的名称并与sorted(vectorizer.get_feature_names())的输出进行比较吗?【参考方案2】:

CountVectorizerTfidfVectorizer 可以按照docs 中的说明进行自定义。特别是,您需要编写一个自定义标记器,它是一个接收文档并返回术语列表的函数。使用 NLTK:

import nltk.corpus.stopwords
import nltk.stem

def smart_tokenizer(doc):
    doc = doc.lower()
    doc = re.findall(r'\w+', doc, re.UNICODE)
    return [nltk.stem.PorterStemmer().stem(term)
            for term in doc
            if term not in nltk.corpus.stopwords.words('english')]

演示:

>>> v = CountVectorizer(tokenizer=smart_tokenizer)
>>> v.fit_transform([doc]).toarray()
array([[1, 1, 1, 2, 1, 1, 1, 1, 1]])
>>> from pprint import pprint
>>> pprint(v.vocabulary_)
u'amaz': 0,
 u'appl': 1,
 u'best': 2,
 u'ear': 3,
 u'ever': 4,
 u'headphon': 5,
 u'pod': 6,
 u'sound': 7,
 u've': 8

(我链接到的示例实际上使用了一个类来缓存词形分析器,但是一个函数也可以。)

【讨论】:

这不处理标点符号或自定义词(如josilber's answer 中的“apple”)。 @raxacoricofallapatorius 这只是一个例子。关键是你可以写一个 Python 函数并将其插入;该功能的作用完全取决于您。您几乎可以插入 josilber 的功能。

以上是关于在 python 中完全复制 R 文本预处理的主要内容,如果未能解决你的问题,请参考以下文章

Python小练:(五:异常处理)

python 文件处理

求助:如何用python脚本删除文本中的重复行(相同记录只保留一个)

转载python解决文本乱码问题及文本二进制读取后的处理

python文本处理

Python 2.7复制并粘贴超链接文本