Python 匹配多个数据帧之间的子字符串,并在单独的列中求和加权值

Python 匹配多个数据帧之间的子字符串,并在单独的列中求和加权值,python,python-3.x,string,pandas,Python,Python 3.x,String,Pandas,我试图根据是否包含来自另一个数据帧的1个子字符串或多个子字符串,对名为关键字的字符串列表进行分类 对子字符串进行加权,使每个关键字的末尾在大约4列中具有权重。这些列将被称为贷款,抵押,账户,以及卡 我尝试使用join()、concat()和merge()来连接多个数据帧,还尝试使用where()、isin()和contains() 为了达到我想要的目标,我已经接近了好几次,但由于错误或可伸缩性而受阻。我对Python和Pandas的经验有限,因此可能有一种完全不同的方法,我没有考虑过 将熊猫作为

我试图根据是否包含来自另一个数据帧的1个子字符串或多个子字符串,对名为
关键字的字符串列表进行分类

对子字符串进行加权,使每个
关键字
的末尾在大约4列中具有权重。这些列将被称为
贷款
抵押
账户
,以及

我尝试使用
join()
concat()
merge()
来连接多个数据帧,还尝试使用
where()
isin()
contains()

为了达到我想要的目标,我已经接近了好几次,但由于错误或可伸缩性而受阻。我对Python和Pandas的经验有限,因此可能有一种完全不同的方法,我没有考虑过

将熊猫作为pd导入
df=pd.read\u csv('Inputs/keyword.csv',header=0)
df['loan']=0
df2=pd.read\u csv('Essentials/Groups/loans.csv',header=0)
#查看df中的数据
打印(df.head())
输出:
关键词搜索量贷款
0贷款132000 0
1资助圈81000
2政府36000
3短期贷款300000
4公司27000
在上面的代码中,我正在加载我的关键字列表,包括一个关联的搜索卷。它目前没有loan列,所以我添加了一个默认值设置为0的列

下面,我有另一个数据帧,它包括一个术语列表和相关的权重。我任意选择了一个5的整数,我想把它加到现有的总数中

#查看df2中的数据
打印(df2.head())
输出:
术语权重
0贷款5
1贷款5
2个人3
3业务3
4月4日
我发现了一个问题,但不知道如何解决

我的列表包括
贷款
贷款
。把这些复制品放在我的头上对我来说很好。但是,第3行的值为“短期贷款”,并标记为False

由于
贷款
贷款
这两个术语都出现在
短期贷款
中,因此我希望它被标记为True。我尝试反转
.isin()
语句,以便在
df['keywords']
中搜索
df2['terms']
,但结果是一样的

#检查真/假重叠
打印(df['keywords'].isin(df2['terms']).head())
输出:
0对
1错误
2错误
3错误
4错误
最后,一旦我们解决了这个布尔问题,我就不知道如何根据匹配来向量化
df['loan']
中的总和变化。我试图避免for循环,因为我希望关键字列表包含100000多行,每个类别数据框可能包含1000个术语

所需的输出如下所示:

输出:
关键词搜索\批量贷款抵押贷款账户卡
0贷款132000 10000
1资助圈81000
2政府36000
3短期贷款30000 100
4公司27000

df1
视为:

           keywords  search_volume
0             loans         132000
1    funding circle          81000
2        government          36000
3  short term loans          30000
4           company          27000

您可以借助我们的帮助,我们可以采取以下措施:

d=df2.set_index('terms')['weight']
pat=r'({})'.format('|'.join(df2.terms))
#'(loan|loans|personal|business|apr)'
df1=df1.assign(**{'term_match':df1.keywords.str.extract(pat,expand=False),
              'weight':df1.keywords.str.extract(pat,expand=False).map(d)})
print(df1)

输出

           keywords  search_volume term_match  weight
0             loans         132000       loan     5.0
1    funding circle          81000        NaN     NaN
2        government          36000        NaN     NaN
3  short term loans          30000       loan     5.0
4           company          27000        NaN     NaN
编辑 为了找到所有匹配的字符串,让我们将
df2
更新为:
df2.loc[5]=['term',3]
仅用于测试

然后使用:



下面是一种查找匹配数量的方法。这可能会在正确的方向上帮助你

首先使用以下方法分解字符串以分隔行:

然后我们使用
difflib
模块获得最接近的匹配,例如
loan
loans

import difflib

df['loan'] = df.set_index('keywords').index.map(lambda x: difflib.get_close_matches(x, df2.set_index('terms').index))

     keywords  search_volume           loan
0       loans         132000  [loans, loan]
1     funding          81000             []
1      circle          81000             []
2  government          36000             []
3       short          30000             []
3        term          30000             []
3       loans          30000  [loans, loan]
4     company          27000             []
然后我们对索引进行分组,以获取原始数据帧,并计算匹配的长度:

df = df.groupby(df.index).agg({'keywords':' '.join,
                               'search_volume':'last',
                               'loan':'last'})

df['count'] = df['loan'].str.len()

           keywords  search_volume           loan  count
0             loans         132000  [loans, loan]      2
1    funding circle          81000             []      0
2        government          36000             []      0
3  short term loans          30000  [loans, loan]      2
4           company          27000             []      0

剩下的唯一一件事就是将计数与权重相乘,你得到了你想要的。

loan 10在你的预期输出中是什么样子的?@Erfan loan和loans都可以放在“loans”中,所以它是5+5。你是在寻找
df1.keywords.str.contains(r'\b{}\b'.format('|'.join(df2.terms))
[真,假,假,真,假]
?根据您提供的输入,预期的输出是如何的?@anky_91这看起来是正确的输出,但我不完全确定您编写的代码中发生了什么。我的想法是,我有一个大约
100,00个关键字和大约
1000个术语的列表,然后将用于对这些k进行分类eywords。例如,如果关键字是一种贷款类型,它将包括与贷款相关的术语。下面是一个较长的关键字示例,可以更清楚地说明我为什么对每个术语进行加权:
如何获得信用不良的初创企业贷款
诸如“如何”等词表示问题,而“信用不良”和“贷款”表示贷款。@RowanCollins收到了,但有一个问题,您打算如何在这里创建新列,一个匹配
术语的列和填充值是否足够?这看起来非常好,我在匹配
df2
术语时将
weight
列修改为
loan
。这对我们很有用当前的最高值,而不是总额。例如,如果存在
[[loans,5],[term,3]]
,则短语“短期贷款”结果应该是8。使用上述方法,我几乎达到了我需要的程度-但这不是所有匹配项的总和-只是单个匹配项的权重。@RowanCollins您可以添加一列
df1['sum_weights']=df1.groupby('term_match')。weight.transfo
df = explode_str(df, 'keywords', ' ')

     keywords  search_volume  loan
0       loans         132000     0
1     funding          81000     0
1      circle          81000     0
2  government          36000     0
3       short          30000     0
3        term          30000     0
3       loans          30000     0
4     company          27000     0
import difflib

df['loan'] = df.set_index('keywords').index.map(lambda x: difflib.get_close_matches(x, df2.set_index('terms').index))

     keywords  search_volume           loan
0       loans         132000  [loans, loan]
1     funding          81000             []
1      circle          81000             []
2  government          36000             []
3       short          30000             []
3        term          30000             []
3       loans          30000  [loans, loan]
4     company          27000             []
df = df.groupby(df.index).agg({'keywords':' '.join,
                               'search_volume':'last',
                               'loan':'last'})

df['count'] = df['loan'].str.len()

           keywords  search_volume           loan  count
0             loans         132000  [loans, loan]      2
1    funding circle          81000             []      0
2        government          36000             []      0
3  short term loans          30000  [loans, loan]      2
4           company          27000             []      0