【问题标题】:Creating a TfidfVectorizer over a text column of huge pandas dataframe在大熊猫数据框的文本列上创建 TfidfVectorizer
【发布时间】:2019-05-14 05:16:41
【问题描述】:

我需要从存储在巨大dataframe 列中的文本中获取 TF-IDF 特征矩阵,该文本从 CSV 文件(无法放入内存)加载。我正在尝试使用块迭代数据帧,但它返回的生成器对象不是方法TfidfVectorizer 的预期变量类型。我想我在编写生成器方法时做错了ChunkIterator如下所示。

import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer


#Will work only for small Dataset
csvfilename = 'data_elements.csv'
df = pd.read_csv(csvfilename)
vectorizer = TfidfVectorizer()
corpus  = df['text_column'].values
vectorizer.fit_transform(corpus)
print(vectorizer.get_feature_names())



#Trying to use a generator to parse over a huge dataframe
def ChunkIterator(filename):
    for chunk in pd.read_csv(csvfilename, chunksize=1):
       yield chunk['text_column'].values

corpus  = ChunkIterator(csvfilename)
vectorizer.fit_transform(corpus)
print(vectorizer.get_feature_names())

任何人都可以建议如何修改上面的ChunkIterator 方法,或使用dataframe 的任何其他方法。我想避免为dataframe 中的每一行创建单独的文本文件。以下是一些用于重新创建场景的虚拟 csv 文件数据。

id,text_column,tags
001, This is the first document .,['sports','entertainment']
002, This document is the second document .,"['politics', 'asia']"
003, And this is the third one .,['europe','nato']
004, Is this the first document ?,"['sports', 'soccer']"

【问题讨论】:

    标签: python pandas dataframe scikit-learn tfidfvectorizer


    【解决方案1】:

    该方法可以很好地接受生成器。但它需要一个原始文档的可迭代,即字符串。您的生成器是 numpy.ndarray 对象的可迭代对象。所以试试类似的东西:

    def ChunkIterator(filename):
        for chunk in pd.read_csv(csvfilename, chunksize=1):
            for document in chunk['text_column'].values:
                yield document
    

    注意,我真的不明白你为什么在这里使用熊猫。只需使用常规的csv 模块,例如:

    import csv
    def doc_generator(filepath, textcol=0, skipheader=True):
        with open(filepath) as f:
            reader = csv.reader(f)
            if skipheader:
                next(reader, None)
            for row in reader:
                yield row[textcol]
    

    因此,在您的情况下,将 1 传递给 textcol,例如:

    In [1]: from sklearn.feature_extraction.text import TfidfVectorizer
    
    In [2]: import csv
       ...: def doc_generator(filepath, textcol=0, skipheader=True):
       ...:     with open(filepath) as f:
       ...:         reader = csv.reader(f)
       ...:         if skipheader:
       ...:             next(reader, None)
       ...:         for row in reader:
       ...:             yield row[textcol]
       ...:
    
    In [3]: vectorizer = TfidfVectorizer()
    
    In [4]: result = vectorizer.fit_transform(doc_generator('testing.csv', textcol=1))
    
    In [5]: result
    Out[5]:
    <4x9 sparse matrix of type '<class 'numpy.float64'>'
        with 21 stored elements in Compressed Sparse Row format>
    
    In [6]: result.todense()
    Out[6]:
    matrix([[ 0.        ,  0.46979139,  0.58028582,  0.38408524,  0.        ,
              0.        ,  0.38408524,  0.        ,  0.38408524],
            [ 0.        ,  0.6876236 ,  0.        ,  0.28108867,  0.        ,
              0.53864762,  0.28108867,  0.        ,  0.28108867],
            [ 0.51184851,  0.        ,  0.        ,  0.26710379,  0.51184851,
              0.        ,  0.26710379,  0.51184851,  0.26710379],
            [ 0.        ,  0.46979139,  0.58028582,  0.38408524,  0.        ,
              0.        ,  0.38408524,  0.        ,  0.38408524]])
    

    【讨论】:

    • 感谢@juanpa.arrivillaga 提出替代方案。我也有同样的想法。我想是我缺乏对生成器的了解让我一直专注于数据帧。我会尝试两者并选择性能更快的。
    • @juanpa.arrivillaga 谢谢你在这里的回答,这绝对是有帮助的!似乎除了最后一步,我什么都能得到。当我运行 result.todense() 时,我得到一个内存错误。实际上,我想要得到的是作为 pandas 数据框的结果,而我过去使用的代码是: pd.DataFrame(result.toarray(), columns=vectorizer.get_feature_names()) 但它也得到了我是一个内存错误。你知道为什么吗?如何修复它以获取没有 MemoryError 的 pandas 数据帧?谢谢!
    • @mkheifetz 很好,可能是因为您没有足够的内存来创建一个密集的数据结构。为什么不直接使用稀疏表示?
    • @juanpa.arrivilagga,你是怎么做到的?
    • @mkeifetz 那是你在打电话给.todense之前已经拥有的东西了
    猜你喜欢
    • 1970-01-01
    • 2020-02-17
    • 1970-01-01
    • 2016-08-28
    • 1970-01-01
    • 1970-01-01
    • 2018-12-25
    • 2019-12-21
    • 2019-06-07
    相关资源
    最近更新 更多