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 合并

Pandas 基于索引/列组合合并 DataFrame