2014-04-01 47 views
5

我想用我可以在R中使用的相同方式使用Python預處理文檔語料庫。例如,給定初始語料庫corpus,我想最後進行預處理對應於一個語料庫使用下述R代碼產生:準確複製python中的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耳莢是驚人的!入耳式耳機的最佳音效我曾有過 !

耳莢amaz最好的聲音inear headphon香港專業教育學院以往任何時候都

+0

自然語言處理中使用NLTK在Python中。 – ramcdougal

+0

@ramcdougal:我收集了很多,但我正在努力處理文檔。 – orome

+0

看看這個[教程](http://nbviewer.ipython.org/urls/gist.githubusercontent.com/kljensen/9662971/raw/4628ed3a1d27b84a3c56e46d87146c1d08267893/NewHaven.io+NLP+tutorial.ipynb?create=1)。它涵蓋了標記化,停用詞和詞幹。 – ramcdougal

回答

3

似乎棘手的事情正是在預處理步驟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) 

正如你所看到的,存儲的元素和術語的數量恰好這兩種方法之間現在匹配。

+0

有沒有辦法將它傳遞給'scikit-learn'的'CountVectorizer'構造函數。文件使它看起來應該是可能的,但我不知道如何。 – orome

+1

@raxacoricofallapatorius更新爲包含'CountVectorizer'。很高興看到有人在Python中使用15.071x內容! – josliber

+0

謝謝。我是新來的R(我討厭)Python(這很棒)和分析,所以很難。我希望課程是用Python教的! – orome

1

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

演示:(我聯繫的例子來實際使用類緩存lemmatizer,但功能也工作)

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

+0

這不處理標點符號或自定義詞語(如[josilber的答案](http://stackoverflow.com/a/22798822/656912)中的「apple」)。 – orome

+0

@raxacoricofallapatorius這只是一個例子。關鍵是您可以編寫一個Python函數並將其插入;這個功能的作用完全取決於你。你幾乎可以插入josilber的函數。 –