【问题标题】:Matching word in column list in pandas and assign score匹配熊猫列列表中的单词并分配分数
【发布时间】:2020-09-23 00:18:57
【问题描述】:

我有以下两个数据集 - 一个带有文本的数据集:

text = {'Text':[['Nike', 'invests', 'in', 'shoes'], ['Adidas', 'invests', 'in',  't-shirts']]}
text_df = pd.DataFrame(text)
text_df

以及包含单词和相应分数和主题的数据集。

points = {'Text':['invests', 'shoes', 'Adidas'], 'Score':[1, 2, 1], 'Topic':['not_name', 'not_name', 'name' ] }
points_df = pd.DataFrame(points)
points_df

对于文本数据集中的每一行,我想看看这个词是否存在,如果这个词存在, 创建一个以类别命名的列,并创建一个包含相关单词分数的新列表。如果单词不存在,则分配零。

这就是结果

text_results = {'Text':[['Nike', 'invests', 'in', 'shoes'], ['Adidas', 'invests', 'in',  't-shirts']], 'not_name': [[0, 1, 0, 2], [0, 1, 0, 0]], 'name': [[0, 0, 0, 0], [1, 0, 0, 0]]}
results_df = pd.DataFrame(text_results)
results_df

有什么建议吗?我在海上有点迷路了!

【问题讨论】:

    标签: python pandas list


    【解决方案1】:

    首先是points_df 中的值,由DataFrame.pivot_table 旋转,替换缺失值并由DataFrame.to_dict 创建字典:

    df1 = points_df.pivot_table(index='Text',
                                columns='Topic',
                                values='Score', 
                                fill_value=0, 
                                aggfunc='sum')
    d = df1.to_dict('index')
    print (d)
    {'Adidas': {'name': 1, 'not_name': 0}, 
     'invests': {'name': 0, 'not_name': 1}, 
     'shoes': {'name': 0, 'not_name': 2}}
    

    从列名创建字典,由 0 值填充,用于不存在的值:

    missd = dict.fromkeys(df1.columns, 0)
    print (missd)
    {'name': 0, 'not_name': 0}
    

    然后对于text_df['Text'] 中列表的每个值,dict.get 的映射值,因此如果无法匹配,则使用默认缺失值字典:

    L = [[d.get(y, missd) for y in x] for x in text_df['Text']]
    

    然后是this solution在列表理解中将格式从字典列表更改为列表字典:

    L = [{k: [dic[k] for dic in x] for k in x[0]} for x in L]
    print (L)
    [{'name': [0, 0, 0, 0], 'not_name': [0, 1, 0, 2]}, 
     {'name': [1, 0, 0, 0], 'not_name': [0, 1, 0, 0]}]
    

    最后创建DataFrame并添加到text_df:

    df = text_df.join(pd.DataFrame(L, index=text_df.index))
    print (df)
                                  Text          name      not_name
    0       [Nike, invests, in, shoes]  [0, 0, 0, 0]  [0, 1, 0, 2]
    1  [Adidas, invests, in, t-shirts]  [1, 0, 0, 0]  [0, 1, 0, 0]
    

    【讨论】:

    • 您好,谢谢!当我旋转第一行“ValueError:索引包含重复条目,无法重塑”中的数据时,我立即收到错误消息。如果有帮助,这是实际的 point_df 数据docs.google.com/spreadsheets/d/e/…
    • @FilippoSebastio - 问题在于重复,这里使用pivot_table 而不是pivot,我希望解决方案运作良好。
    • 谢谢!运行以下命令时遇到错误:L = [[d.get(y,missd) for y in x] for x in train_data.tokenized_sentences] TypeError: unhashable type: 'list'
    • @FilippoSebastio - 嗯,这意味着数据有问题。是否可以共享两个 DataFrames/文件?
    • 成功了!对不起,这是我的错误,你的代码很好。再次感谢您的帮助!
    【解决方案2】:

    使用df.reindex的另一种解决方案

    创建自定义函数。首先,使用df.set_index'Text' 设置为索引,然后使用df.reindex 它们。现在使用df.where 提取'Score' 列,其中'Topic'not_namename,将它们转换为列表或NumPy 数组pd.Series.tolistpd.Series.to_numpy() 然后使用df.join 加入它们。

    points_df.set_index('Text',inplace=True)
    def func(x):
        x = points_df.reindex(x)
        m = x['Score'].where(x['Topic']=='not_name',0).to_numpy()
        n = x['Score'].where(x['Topic']=='name',0).to_numpy()
        return pd.Series([n,m],index=['name','not_name'])
    
    t = text_df['Text'].apply(func)
    
    text_df.join(t) # or df.merge(t,left_index=True,right_index=True)
                                  Text                  name              not_name
    0       [Nike, invests, in, shoes]  [0.0, 0.0, 0.0, 0.0]  [0.0, 1.0, 0.0, 2.0]
    1  [Adidas, invests, in, t-shirts]  [1.0, 0.0, 0.0, 0.0]  [0.0, 1.0, 0.0, 0.0]
    

    【讨论】:

    • 谢谢!当我将函数应用于 text_df 时,它返回一个错误:ValueError:所有数组必须是相同的长度,可能是因为返回的系列有不同的长度?
    • 你能发布失败的数据吗? @FilippoSebastio
    • docs.google.com/spreadsheets/d/e/… 在这里,谢谢!
    【解决方案3】:

    使用explodemerge 的另一种方式:

    s =  text_df.explode("Text").reset_index().merge(points_df, on="Text", how="left").set_index("index").fillna(0)
    
    print (s.assign(Score=np.where(s["Topic"].eq("name"),0,s["Score"]))
            .replace({"Topic":{"not_name":0, "name":1}})
            .rename(columns={"Score":"not_name","Topic":"name"})
            .groupby(level=0).agg(list))
    
                                      Text              not_name          name
    index                                                                     
    0           [Nike, invests, in, shoes]  [0.0, 1.0, 0.0, 2.0]  [0, 0, 0, 0]
    1      [Adidas, invests, in, t-shirts]  [0.0, 1.0, 0.0, 0.0]  [1, 0, 0, 0]
    

    【讨论】:

    • 您好,谢谢您,但是在运行第一行时会返回错误,“TypeError: unhashable type: 'list'”
    【解决方案4】:

    首先最好使用Text 列索引points_df

    points_df.set_index('Text', inplace=True)
    

    接下来,我们通过复制 text_df 并为所有主题创建单独的列来创建结果 res 数据框

    res = text_df.copy()
    for category in list(points_df['Topic'].unique()):
        res[category] = res['Text']
    
    for i in range(len(res)):
        for j in res.columns[1:]:
            res.at[i, j] = [0] * len(res.loc[i,'Text'])
    

    以下逻辑是根据您的需要更改列表中的值

    
    for i in range(len(res)):
        l = res.loc[i]
    
        for i,word in enumerate(l['Text']):
            if word in list(points_df.index):
                cat = points_df.loc[word]['Topic']
                l[cat][i] = points_df.loc[word, 'Score']
    
    

    最后res 数据框如下:

        Text    not_name    name
    0   [Nike, invests, in, shoes]  [0, 1, 0, 2]    [0, 0, 0, 0]
    1   [Adidas, invests, in, t-shirts] [0, 1, 0, 0]    [1, 0, 0, 0]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-01-29
      • 1970-01-01
      • 1970-01-01
      • 2021-08-08
      • 1970-01-01
      • 2019-04-23
      • 2021-06-05
      • 1970-01-01
      相关资源
      最近更新 更多