我正在尝试与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