在Python值范围内的多个条件下匹配两个数据框

问题描述

我需要一些技巧/线索,说明如何在多个条件下匹配Python中的两个数据框,其中一些条件正在寻找范围内的值。示例:

1。第一个数据帧是一个合同,其中我们具有以下位置:国家/地区,邮政编码低,邮政编码高,国家/地区,邮政编码低,邮政编码高,合同ID。

from country from postal code low from postal code high to country to postal code low to postal code high ID
SE         0         19999            DE      90000         99999   ID1
SE     20000         29999            DE      90000         99999   ID2
SE     30000         39999            DE      90000         99999   ID3
SE     40000         49999            DE      90000         99999   ID4
SE     41250         41250            DE      90000         99999   ID5

2。第二个数据帧是统计文件,其中包含确切的邮政编码,我需要从第一个数据库中查找所有唯一匹配项:

From country  from postal code    to country  To postal code   ID (that should be the result):
SE              21789              DE          91000            ID2
SE              41250              DE          91000            ID4,ID5

在excel中,这可以通过索引和匹配以及数组函数来完成,因为两个数据框都涉及数万甚至数十万行,所以在excel中进行操作不是最佳选择,因此希望使用Python解决方案。我是Python的初学者,因此至少对我应该研究的内容有所帮助。我知道pandas合并功能,但是它要求列的完全匹配,是否可以帮助pandassql,但是我不确定如何将另一个数据库作为其中邮政编码 =邮政编码的条件代码高吗?

有什么提示吗?

df的可视化:

enter image description here

解决方法

一种方法是进行嵌套列表理解:

df2["ID"] = [[idx for lo,hi,idx in zip(df["from postal code low"],df["from postal code high"],df["ID"]) if i in range(lo,hi+1)]
             for i in df2["from postal code"]]

print (df2)

  From country  from postal code to country  To postal code          ID
0           SE             21789         DE           91000       [ID2]
1           SE             41250         DE           91000  [ID4,ID5]
,

一种方法是直接遍历所有选项,在这种情况下,如果在循环中使用语法,则将范围cols缩短了:

contract_df['from_range'] = [range(t[0],t[1]) for t in zip(contract_df['from_postal_code_low'],contract_df['from_postal_code_high']+1)]
contract_df['to_range'] = [range(t[0],t[1]) for t in zip(contract_df['to_postal_code_low'],contract_df['to_postal_code_high']+1)]

lol = []
for r in stat_df.iterrows():
    l = []
    for r1 in contract_df.iterrows():
        if (r[1]['from_country'] == r1[1]['from_country']) and (r[1]['to_country'] == r1[1]['to_country']) and (r[1]['from_postal_code'] in r1[1]['from_range']) and (r[1]['to_postal_code'] in r1[1]['to_range']):
            l.append(r1[1]['ID'])
    lol.append(l)

stat_df['ID'] = lol