【问题标题】:Map values from another dataframe within multiple conditions在多个条件下映射来自另一个数据帧的值
【发布时间】:2021-05-21 08:18:24
【问题描述】:

希望使用条件将最高匹配行值从 Dataframe2 映射到 Dataframe1。我们还需要检查 df2['from'] 和 df['to'] 之间的 df1['sal_date'] 。

想要将 df1 中的每一行(df1['id_number'])与 df2 的整列(df2['identity_No'])进行比较。我已申请使用部分匹配来提取条件及其工作,

但我如何检查 df1['sal_date'] 是否属于 df2['from'] 和 df['to'] 中的哪一个。

df1

score   id_number       company_name      company_code        sal_date     action_reqd
20      IN2231D           AXN pvt Ltd        IN225           2019-12-22        Yes
45      UK654IN        Aviva Intl Ltd        IN115           2018-10-10        No
65      SL1432H   Ship Incorporations        CZ555           2015-08-19        Yes
35      LK0678G  Oppo Mobiles pvt ltd        PQ795           2018-06-26        Yes
59      NG5678J             Nokia Inc        RS885           2020-12-28        No
20      IN2231D           AXN pvt Ltd        IN215           2020-12-08        Yes

df2

OR_score   identity_No       comp_name        comp_code   dte_from        dte_to
51          UK654IN        Aviva Int.L Ltd       IN515    2017-12-05    2018-10-13
25          SL6752J       Ship Inc Traders       CZ555    2013-08-07    2022-06-21
79          NG5678K             Nokia Inc        RS005    2018-10-13    2019-12-15
51          UK654IN        Aviva Int.L Ltd       IN525    2018-12-15    2020-12-24
20          IN22312           AXN pvt Ltd        IN255    2019-12-10    2022-06-21
79          NG5678K             Nokia Inc        RS055    2019-06-08    2024-12-30
38          LK0665G       Oppo Mobiles ltd       PQ895    2016-10-10    2022-12-08
20          IN22312           AXN pvt Ltd        IN275    2017-08-17    2018-10-13
75          NG5678K             Nokia Inc        RS055    2013-06-08    2016-12-30

df1.id_number 需要与 df2.identity_No 进行比较,df1.sal_date 必须在 df2.from 和 df2.to 之间。

根据 df1['id_number'] 的第 1 行查找匹配将匹配 df2['identity_No'] 的所有行,并且匹配百分比最高。 df2['identity_No'] 的第 4 行,超过 80%,且 df1.sal_date 介于 df2.from 和 df2.to 之间。

它会将相应的值从 df2 的第 4 行复制到 df1 的第 1 行。 同样适用于 df1 的每一行。

预期输出:

score   id_number       company_name      company_code          match_acc     action_reqd
20      IN22312           AXN pvt Ltd        IN255              2019-12-22          Yes
51      UK654IN       Aviva Int.L Ltd        IN515              2018-10-10          No
25      SL1432H   Ship Incorporations        CZ555              2015-08-19          Yes
38      LK0665G      Oppo Mobiles ltd        PQ795              2018-06-26          Yes
79      NG5678K             Nokia Inc        RS055              2020-12-28          No
20      IN22312           AXN pvt Ltd        IN255              2020-12-08          Yes

我现在已经试过了:

for index, row in df1.iterrows():
    for index2, config2 in df2.iterrows():
        variable = fuzz.partial_ratio(row['id_number'], config2['identity_No'])
        if variable>=80:
            df1['id_number'][index] = config2['identity_No']
            df1['company_name'][index] = config2['comp_name']
            df1['company_code'][index] = config2['comp_code']
            df1['score'][index] = config2['OR_Score']

如果条件为变量 >=80% 且 df1.sal_date 介于 df2.from 和 df2.to 之间,我如何执行剩余代码

请建议如何执行。

【问题讨论】:

  • 如果 df1['id_number'] 匹配超过 80% 与 2 个或更多 df2['identity_No'] 怎么办?
  • @Ank - 除了检查超过 80% 的匹配,我们还需要检查 df1['sal_date'] 是否在 df2['from'] 和 df2['to'] 之间。
  • 是的,我明白了,如果在应用这两个条件后,df1 中的一行映射到 df2 中的 2 行或更多行?
  • 或者确定这两个条件都应用后,只有1:1的映射?
  • 哦,是的,不,那只是数学方程式,抱歉。只是想弄清楚这个逻辑是否足够。

标签: python pandas


【解决方案1】:

您的代码有两个主要缺陷:

  1. 根据您对问题的描述(如下),df1['sal_date'] 是否在dte_fromdte_to 之间是必要条件,因此应首先检查。第二步是返回可能的最高匹配。由于您要强制进行 1:1 映射,匹配 >=80 并不重要,您只需返回最高的匹配。

希望使用条件将最高匹配行值从 Dataframe2 映射到 Dataframe1。我们还需要检查 df2['from'] 和 df['to'] 之间的 df1['sal_date']。

  1. 您的代码并没有真正返回来自df2 的最高匹配百分比超过80% 的行,但它返回最后一个。每次满足条件variable>=80 时,df1 中的当前行都会被覆盖。

另外,df2 中第 1 列的名称不一致;在df2 中称​​为OR_score,小写s,但在代码中称为OR_Score,大写S

我稍微更改了您的代码。我添加了highest_match,它跟踪最高匹配的variable 是什么,并且仅在新匹配的variable 高于最高匹配时覆盖。如果df1,这将为每一行重置。

我不使用>=,因此如果variable 相等,它会保留第一个匹配项。如果你想保持你的>=80 条件,你可以初始化highest_match = 80,但是如果df1 的一行没有找到匹配的>=80 并且该行就保持原样,这个代码会警告你。

如果首先满足日期条件,代码也只会继续。

from fuzzywuzzy import fuzz

for index, row in df1.iterrows():
    highest_match = 0
    for index2, config2 in df2.iterrows():
        cond1 = df1['sal_date'][index] <= config2['dte_to']
        cond2 = df1['sal_date'][index] >= config2['dte_from']
        if cond1 and cond2:
            variable = fuzz.partial_ratio(row['id_number'], config2['identity_No'])
            if variable > highest_match:
                df1['id_number'][index] = config2['identity_No']
                df1['company_name'][index] = config2['comp_name']
                df1['company_code'][index] = config2['comp_code']
                df1['score'][index] = config2['OR_score']
                highest_match = variable

这段代码没有针对时间复杂度进行优化,它只是完成了您想要完成的工作。或者至少它会产生您预期的输出。添加&gt;=80 约束可能会缩短时间,但是您需要添加一些逻辑来说明如果没有匹配项&gt;=80 会发生什么。

请添加您下次如何创建表的代码,而不仅仅是输出。这样可以更轻松地重现您的问题,并且会有更多人愿意提供帮助,谢谢。

编辑:

如果您想保留缺少sal_date 的行,只需跳过它们:

from fuzzywuzzy import fuzz

for index, row in df1.iterrows():
    if pd.isna(row['sal_date']):
        continue
    highest_match = 0
    for index2, config2 in df2.iterrows():
        cond1 = df1['sal_date'][index] <= config2['dte_to']
        cond2 = df1['sal_date'][index] >= config2['dte_from']
        if cond1 and cond2:
            variable = fuzz.partial_ratio(row['id_number'], config2['identity_No'])
            if variable > highest_match:
                df1['id_number'][index] = config2['identity_No']
                df1['company_name'][index] = config2['comp_name']
                df1['company_code'][index] = config2['comp_code']
                df1['score'][index] = config2['OR_score']
                highest_match = variable

【讨论】:

  • 当有任何空白/NaN 值时,会发生错误。 TypeError:“float”和“str”实例之间不支持“>=”
  • 好吧,这不是一个真正的stackoverflow问题,你只需要弄清楚你想对丢失的数据做什么。如果没有dte_to,你认为它还在继续吗?然后将dte_to 设置为pd.Timestamp.now()。如果您想做出最坏情况的假设,您需要将其设置为dte_from。最终,这些问题只能通过您的领域专业知识来回答。我敦促您用有意义的值填充缺失的数据,然后运行代码。您可以在代码中添加逻辑来处理这个问题,但这不是我个人解决问题的方式。
  • 在上述情况下,我遇到 df1['sal_date'] 也具有 NaN 值的情况,我想跳过 df1['sal_date'] = NaN 的行,我如何可以处理 NaN 值,因为它给出了 Error: TypeError: '>=' not supported between 'float' and 'str'
  • 我尝试将 cond1 = df1['sal_date'][index]
  • @NKJ 检查编辑,应该做你在另一个问题的预期输出中显示的内容。
猜你喜欢
  • 1970-01-01
  • 2023-03-21
  • 2019-10-17
  • 2018-05-30
  • 1970-01-01
  • 1970-01-01
  • 2013-06-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多