在熊猫的列列表中匹配单词并分配分数

时间:2020-06-04 05:29:04

标签: python pandas list

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

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

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

4 个答案:

答案 0 :(得分: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中list的每个值映射值,因此,如果无法匹配,请使用默认的缺失值字典:

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]

答案 1 :(得分:1)

使用df.reindex

的另一种解决方案

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

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]

答案 2 :(得分:1)

使用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]

答案 3 :(得分:0)

首先,最好使用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]