【问题标题】:Append tfidf to pandas dataframe将 tfidf 附加到熊猫数据框
【发布时间】:2018-02-08 05:55:18
【问题描述】:

我有以下熊猫结构:

col1 col2 col3 text
1    1    0    meaningful text
5    9    7    trees
7    8    2    text

我想使用 tfidf 矢量化器对其进行矢量化。然而,这会返回一个解析矩阵,我实际上可以通过mysparsematrix).toarray() 将其变成一个密集矩阵。但是,如何将这些带有标签的信息添加到我的原始 df 中?所以目标看起来像:

col1 col2 col3 meaningful text trees
1    1    0    1          1    0
5    9    7    0          0    1
7    8    2    0          1    0

更新:

即使重命名原始列,解决方案也会导致连接错误: 即使我在开始使用它之前使用fillna(0),删除具有至少一个 NaN 的列也会导致只剩下 7 行。

【问题讨论】:

    标签: python dataframe tf-idf sklearn-pandas


    【解决方案1】:

    您可以按照以下方式进行:

    将数据加载到数据框中:

    import pandas as pd
    
    df = pd.read_table("/tmp/test.csv", sep="\s+")
    print(df)
    

    输出:

       col1  col2  col3             text
    0     1     1     0  meaningful text
    1     5     9     7            trees
    2     7     8     2             text
    

    标记text 列使用: sklearn.feature_extraction.text.TfidfVectorizer

    from sklearn.feature_extraction.text import TfidfVectorizer
    
    v = TfidfVectorizer()
    x = v.fit_transform(df['text'])
    

    将标记化的数据转换为数据框:

    df1 = pd.DataFrame(x.toarray(), columns=v.get_feature_names())
    print(df1)
    

    输出:

       meaningful      text  trees
    0    0.795961  0.605349    0.0
    1    0.000000  0.000000    1.0
    2    0.000000  1.000000    0.0
    

    将标记化数据帧连接到原始数据帧:

    res = pd.concat([df, df1], axis=1)
    print(res)
    

    输出:

       col1  col2  col3             text  meaningful      text  trees
    0     1     1     0  meaningful text    0.795961  0.605349    0.0
    1     5     9     7            trees    0.000000  0.000000    1.0
    2     7     8     2             text    0.000000  1.000000    0.0
    

    如果你想删除列text,你需要在连接之前这样做:

    df.drop('text', axis=1, inplace=True)
    res = pd.concat([df, df1], axis=1)
    print(res)
    

    输出:

       col1  col2  col3  meaningful      text  trees
    0     1     1     0    0.795961  0.605349    0.0
    1     5     9     7    0.000000  0.000000    1.0
    2     7     8     2    0.000000  1.000000    0.0
    

    这是完整的代码:

    import pandas as pd
    from sklearn.feature_extraction.text import TfidfVectorizer
    
    df = pd.read_table("/tmp/test.csv", sep="\s+")
    v = TfidfVectorizer()
    x = v.fit_transform(df['text'])
    
    df1 = pd.DataFrame(x.toarray(), columns=v.get_feature_names())
    df.drop('text', axis=1, inplace=True)
    res = pd.concat([df, df1], axis=1)
    

    【讨论】:

    • 这几乎可以工作,但是出了点问题...默认情况下,这会执行外连接,我最终得到 699 行而不是原来的 353 行,有很多 NaN 行...可能出了什么问题?
    • @lte__ 你能分享一个我可以用来重现问题的数据集吗?
    • 不,这是机密数据...我认为文本中的某些单词与标签相同,这会导致外连接行为(就像这里的第一个示例pandas.pydata.org/pandas-docs/stable/… )
    • @lte__ 我建议您为原始数据中的所有列名称添加前缀,然后进行转换。 (something_col1, something_col2, ..)
    • 我不知道,我们通过另一个问题的解决方法解决了这个问题。但为此,您的解决方案实际上是正确的答案。
    【解决方案2】:

    您可以尝试以下方法 -

    import numpy as np 
    import pandas as pd 
    from sklearn.feature_extraction.text import TfidfVectorizer
    
    # create some data
    col1 = np.asarray(np.random.choice(10,size=(10)))
    col2 = np.asarray(np.random.choice(10,size=(10)))
    col3 = np.asarray(np.random.choice(10,size=(10)))
    text = ['Some models allow for specialized',
             'efficient parameter search strategies,',
             'outlined below. Two generic approaches',
             'to sampling search candidates are ',
             'provided in scikit-learn: for given values,',
             'GridSearchCV exhaustively considers all',
             'parameter combinations, while RandomizedSearchCV',
             'can sample a given number of candidates',
             ' from a parameter space with a specified distribution.',
             ' After describing these tools we detail best practice applicable to both approaches.']
    
    # create a dataframe from the the created data
    df = pd.DataFrame([col1,col2,col3,text]).T
    # set column names
    df.columns=['col1','col2','col3','text']
    
    tfidf_vec = TfidfVectorizer()
    tfidf_dense = tfidf_vec.fit_transform(df['text']).todense()
    new_cols = tfidf_vec.get_feature_names()
    
    # remove the text column as the word 'text' may exist in the words and you'll get an error
    df = df.drop('text',axis=1)
    # join the tfidf values to the existing dataframe
    df = df.join(pd.DataFrame(tfidf_dense, columns=new_cols))
    

    【讨论】:

    • ValueError: 列重叠但未指定后缀
    • dftfidf_dense 中是否有同名的列?
    • 我不能确定,因为我在df 中的功能之一是'count',并且'count' 字可能也在tfidf_dense 中。但我能够通过从我的df 中删除索引来解决此错误。感谢您的帮助。
    【解决方案3】:

    我想在接受的答案中添加一些信息。

    在连接两个 DataFrame(即 main DataFrame 和 TF-IDF DataFrame)之前,请确保两个 DataFrame 之间的索引相似。例如,您可以使用 df.reset_index(drop=True, inplace=True) 来重置 DataFrame 索引。

    否则,您的连接 DataFrame 将包含很多 NaN 行。看了cmets,这大概就是OP经历的吧。

    【讨论】:

    • 我遇到了与 lte_ 相同的问题,即行数比预期的多,有很多 NA 值。问题出在索引中。感谢 Glorian 和所有其他人。
    猜你喜欢
    • 2017-06-13
    • 2014-01-03
    • 1970-01-01
    • 2019-01-14
    • 2019-10-22
    • 2021-09-24
    • 2022-11-25
    • 2018-05-24
    • 1970-01-01
    相关资源
    最近更新 更多