Pandas:如何在第二个 DataFrame 的另一列中查找子字符串位置
Posted
技术标签:
【中文标题】Pandas:如何在第二个 DataFrame 的另一列中查找子字符串位置【英文标题】:Pandas : How to find substring position in another column of the second DataFrame 【发布时间】:2021-05-04 04:15:08 【问题描述】:我正在尝试将 df2 中的 products(Product2) 与可能涉及子字符串匹配的 df1["Product1"] 进行匹配。 寻找结果
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)
【问题讨论】:
问题解决了吗?随时询问您是否需要进一步的帮助。如果您以其他方式解决了问题,请分享您的解决方案。 【参考方案1】:您的代码问题:
您的代码不起作用,因为 Product1 和 Product2 位于 2 个不同的 DataFrame 中,因此无法在矢量化数组操作中一起迭代。将 str(df2['Product2'])
传递给 df1 的 pandas 系列的 str.find() 函数很可能只产生以下字符串(标量值),而不是同一行索引的预期矢量化值。
'0 PPP\n1 Ph\n2 Printer\n3 Desk\nName: Product2, dtype: object'
因此,str.find() 不会产生匹配项。
解决方案不简单:
要执行矢量化操作,您必须将 2 个数据帧合并为一个,并对合并的数据帧进行操作。但是,对于更通用的数据输入,连接 2 个数据框的简单列无法完成您的任务。让我们通过一个例子来解释一下。
例如如果 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 匹配的产品。 当 2 个产品集没有按顺序对齐匹配产品时,会导致不匹配。
解决方案中需要笛卡尔积或交叉连接:
要执行您的任务,您必须在中间数据框中构建一个 4 x 4 行的连接,在每行中执行按列的子字符串操作,然后合并结果匹配项。详细步骤如下:
1。交叉连接 df1, df2
通过代码交叉连接 2 个数据帧:
对于 pandas 版本 >= 1.2.0(2020 年 12 月 26 日)
df_combined = df1.merge(df2, how='cross') # how='cross' is new in pandas version 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
【讨论】:
以上是关于Pandas:如何在第二个 DataFrame 的另一列中查找子字符串位置的主要内容,如果未能解决你的问题,请参考以下文章
选择 Pandas DataFrame 的第二个 MultiIndex 级别作为索引器
Python - Pandas Dataframe 以正确的方式合并两个数据框
如何从 Pandas 日期时间索引中删除尾随零(根据需要格式化)?
在以下情况下,如何在第二个 for 循环中访问 (i+1 ) 索引?
将 Pandas Multiindexed DataFrame 与 Singleindexed Pandas DataFrame 合并