J'essaie de créer une matrice de document terme avec NLTK et Pandas. J'ai écrit la fonction suivante:
def fnDTM_Corpus(xCorpus):
import pandas as pd
'''to create a Term Document Matrix from a NLTK Corpus'''
fd_list = []
for x in range(0, len(xCorpus.fileids())):
fd_list.append(nltk.FreqDist(xCorpus.words(xCorpus.fileids()[x])))
DTM = pd.DataFrame(fd_list, index = xCorpus.fileids())
DTM.fillna(0,inplace = True)
return DTM.T
pour le courir
import nltk
from nltk.corpus import PlaintextCorpusReader
corpus_root = 'C:/Data/'
newcorpus = PlaintextCorpusReader(corpus_root, '.*')
x = fnDTM_Corpus(newcorpus)
Cela fonctionne bien pour quelques petits fichiers dans le corpus, mais me donne un MemoryError lorsque j'essaie de l'exécuter avec un corpus de 4 000 fichiers (d'environ 2 Ko chacun).
Est-ce que je manque quelque chose?
J'utilise un python 32 bits. (AM sur Windows 7, système d'exploitation 64 bits, CPU quadrio, 8 Go de RAM). Dois-je vraiment utiliser 64 bits pour corpus de cette taille?
Merci à Radim et Larsmans. Mon objectif était d'avoir un DTM comme celui que vous avez dans R TM. J'ai décidé d'utiliser Scikit-Apprendre et partiellement inspiré par cette entrée de blog . Ce code que j'ai proposé.
Je postez-le ici dans l'espoir que quelqu'un d'autre le trouvera utile.
import pandas as pd
from sklearn.feature_extraction.text import CountVectorizer
def fn_tdm_df(docs, xColNames = None, **kwargs):
''' create a term document matrix as pandas DataFrame
with **kwargs you can pass arguments of CountVectorizer
if xColNames is given the dataframe gets columns Names'''
#initialize the vectorizer
vectorizer = CountVectorizer(**kwargs)
x1 = vectorizer.fit_transform(docs)
#create dataFrame
df = pd.DataFrame(x1.toarray().transpose(), index = vectorizer.get_feature_names())
if xColNames is not None:
df.columns = xColNames
return df
pour l'utiliser sur une liste de texte dans un répertoire
DIR = 'C:/Data/'
def fn_CorpusFromDIR(xDIR):
''' functions to create corpus from a Directories
Input: Directory
Output: A dictionary with
Names of files ['ColNames']
the text in corpus ['docs']'''
import os
Res = dict(docs = [open(os.path.join(xDIR,f)).read() for f in os.listdir(xDIR)],
ColNames = map(lambda x: 'P_' + x[0:6], os.listdir(xDIR)))
return Res
d1 = fn_tdm_df(docs = fn_CorpusFromDIR(DIR)['docs'],
xColNames = fn_CorpusFromDIR(DIR)['ColNames'],
stop_words=None, charset_error = 'replace')
Je sais que l'OP voulait créer un TDM dans NLTK, mais le package textmining
(pip install textmining
) le rend mort simple:
import textmining
def termdocumentmatrix_example():
# Create some very short sample documents
doc1 = 'John and Bob are brothers.'
doc2 = 'John went to the store. The store was closed.'
doc3 = 'Bob went to the store too.'
# Initialize class to create term-document matrix
tdm = textmining.TermDocumentMatrix()
# Add the documents
tdm.add_doc(doc1)
tdm.add_doc(doc2)
tdm.add_doc(doc3)
# Write out the matrix to a csv file. Note that setting cutoff=1 means
# that words which appear in 1 or more documents will be included in
# the output (i.e. every Word will appear in the output). The default
# for cutoff is 2, since we usually aren't interested in words which
# appear in a single document. For this example we want to see all
# words however, hence cutoff=1.
tdm.write_csv('matrix.csv', cutoff=1)
# Instead of writing out the matrix you can also access its rows directly.
# Let's print them to the screen.
for row in tdm.rows(cutoff=1):
print row
termdocumentmatrix_example()
Sortir:
['and', 'the', 'brothers', 'to', 'are', 'closed', 'bob', 'john', 'was', 'went', 'store', 'too']
[1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0]
[0, 2, 0, 1, 0, 1, 0, 1, 1, 1, 2, 0]
[0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1]
En variante, on peut utiliser pandas et Sklearn [Source] :
import pandas as pd
from sklearn.feature_extraction.text import CountVectorizer
docs = ['why hello there', 'omg hello pony', 'she went there? omg']
vec = CountVectorizer()
X = vec.fit_transform(docs)
df = pd.DataFrame(X.toarray(), columns=vec.get_feature_names())
print(df)
Sortir:
hello omg pony she there went why
0 1 0 0 0 1 0 1
1 1 1 1 0 0 0 0
2 0 1 0 1 1 1 0