Pandas:如何在第二个DataFrame的另一列中查找子字符串位置



我正在尝试与df1["Product1"]匹配df2中的产品(Product2),这可能涉及子字符串匹配。查找结果

0    False
1    True 
2    True 
3    True

但是我得到的都是假的。我哪里做错了?

firstProductSet = {'Product1':['Computer','Phone','Printer','Desk'],'Price1':[1200,800,200,350]}
df1 = pd.DataFrame(firstProductSet,columns= ['Product1', 'Price1'])
secondProductSet = {'Product2': ['PPP','Ph','Printer','Desk'],'Price2':[900,800,300,350]}
df2 = pd.DataFrame(secondProductSet,columns= ['Product2', 'Price2'])
print(df2)`enter code here`
#add the Price2 column from df2 to df1
df1['productMatch?'] = np.where(df1['Product1'].str.find(str(df2['Product2'])) !=-1, 'True', 'False')  #create new column in df1 to check if prices match
print (df1)

你的代码问题:

你的代码不能工作,因为Product1和Product2在2个不同的dataframe中,因此不能在向量化数组操作中一起迭代。将str(df2['Product2'])传递给df1的pandas Series的str.find()函数很可能只产生以下字符串(标量值),而不是相同行索引的预期矢量化值。

'0        PPPn1         Phn2    Printern3       DesknName: Product2, dtype: object'

因此,str.find()不会产生匹配。

解决方案不容忽视:

要执行向量化操作,必须将两个数据框合并为一个,并对合并后的数据框进行操作。然而,在两个数据帧上的简单列连接无法实现您的任务获取更多通用数据输入。让我们通过一个例子来解释。

。如果secondProductSet的Product2有稍微不同的组合['Ph','Printer','Desk', 'PPP'],即'PPP'放在列表的末尾. 然后简单的列concat将给出:

Product1  Price1 Product2  Price2  productMatch?
0  Computer    1200       Ph     800          False
1     Phone     800  Printer     300          False
2   Printer     200     Desk     350          False
3      Desk     350      PPP     900          False

当然,这不是我们想要的结果,因为在Product2中实际上有一些与Product1匹配的产品。当两个产品集没有按照匹配产品的顺序对齐时,导致不匹配。

解中需要笛卡尔积或交叉连接:

要执行任务,必须在中间数据框中构建一个给出4 x 4行的连接,在每行中执行逐列子字符串操作,然后合并结果匹配。具体步骤如下:

1。交叉连接df1, df2

用以下代码交叉连接两个数据帧:

熊猫版>= 1.2.0(2020年12月26日)

df_combined = df1.merge(df2, how='cross')     # how='cross' is new in pandas version 1.2.0

熊猫版<1.2.0

df1['join'] = 1
df2['join'] = 1
df_combined = df1.merge(df2, on='join').drop('join', axis=1)
df2.drop('join', axis=1, inplace=True)

结果数据框df_combined (4 x 4 = 16行):

Product1    Price1  Product2    Price2
0   Computer    1200    PPP         900
1   Computer    1200    Ph          800
2   Computer    1200    Printer     300
3   Computer    1200    Desk        350
4   Phone        800    PPP         900
5   Phone        800    Ph          800
6   Phone        800    Printer     300
7   Phone        800    Desk        350
8   Printer      200    PPP         900
9   Printer      200    Ph          800
10  Printer      200    Printer     300
11  Printer      200    Desk        350
12  Desk         350    PPP         900
13  Desk         350    Ph          800
14  Desk         350    Printer     300
15  Desk         350    Desk        350

2。匹配每一行中的子字符串

将Product2中的子字符串与Product1匹配:

df_combined['productMatch?'] = df_combined.apply(lambda x: x.Product1.find(x.Product2), axis=1).ge(0)

ge(0)测试find()>= 0的返回代码[与您检查的结果相同!= -1]

[布尔值True, False返回而不是字符串'True', 'False'在你的代码]

Product1    Price1  Product2    Price2  productMatch?
0   Computer    1200    PPP         900             False
1   Computer    1200    Ph          800             False
2   Computer    1200    Printer     300             False
3   Computer    1200    Desk        350             False
4   Phone        800    PPP         900             False
5   Phone        800    Ph          800              True
6   Phone        800    Printer     300             False
7   Phone        800    Desk        350             False
8   Printer      200    PPP         900             False
9   Printer      200    Ph          800             False
10  Printer      200    Printer     300              True
11  Printer      200    Desk        350             False
12  Desk         350    PPP         900             False
13  Desk         350    Ph          800             False
14  Desk         350    Printer     300             False
15  Desk         350    Desk        350              True

3。合并结果匹配

a)将上述匹配结果按df1的原列进行分组。
b)在groupby对象上使用max()来获取列'match'的最大值(True为1,False为0,因此如果在相同的Product1项中存在任何True,则max()给出True)。

df_result = df_combined.groupby(['Product1', 'Price1'], sort=False).max().reset_index()[['Product1', 'Price1','productMatch?']]

结果:

Product1    Price1  productMatch?
0   Computer    1200            False
1   Phone        800             True
2   Printer      200             True
3   Desk         350             True

最新更新