我有以下两个数据集-带有文本的数据集:
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
有什么建议吗?我在海上有点迷路!
答案 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.set_index
将'Text'
设置为索引,然后使用df.reindex
将它们设置为索引。现在使用df.where
提取'Score'
的列,其中'Topic'
是not_name
和name
,将它们转换为列表或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)
使用explode
和merge
的另一种方式:
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]