我有2个数据帧,我想检查DF1中的开始,结束范围是否在DF2中的开始,结束范围内,对于那些为真,我想打印ID和区域。我想比较DF1的每一行和DF2的每一行。
这些是我的数据框架:
DF1 = pd.DataFrame ({'Start':[500, 850, 1000],
'End':[700, 950, 1200],
'Region':["A", "B", "C"]})
DF2 = pd.DataFrame ({'Start':[200, 800, 1100],
'End':[750, 950, 1250],
'ID':[1, 2, 3]})
DF1
您可以通过.merge()
交叉连接两个数据框,然后使用.query()
过滤具有所需条件的行,如下所示:
DF_out = DF1.merge(DF2, how='cross').query('(Start_x >= Start_y) & (End_x <= End_y)')
如果您的Pandas版本低于1.2.0(2020年12月版本)并且不支持how='cross'
,您可以使用:
DF_out = DF1.assign(key=1).merge(DF2.assign(key=1), on='key').drop('key', axis=1).query('(Start_x >= Start_y) & (End_x <= End_y)')
结果:
Start_x
、End_x
为DF1
中原Start
、End
列
Start_y
,End_y
为DF2
中原Start
,End
列
print(DF_out)
Start_x End_x Region Start_y End_y ID
0 500 700 A 200 750 1
4 850 950 B 800 950 2
你可以很容易地打印Region
和ID
,例如
print(DF_out['Region'])
0 A
4 B
Name: Region, dtype: object
print(DF_out['ID'])
0 1
4 2
Name: ID, dtype: int64
如果您的检查标准严格为<
或>
,而不是<=
或>=
,则可以修改.query()
中的比较运算符符号,如下所示:
DF_out = DF1.merge(DF2, how='cross').query('(Start_x > Start_y) & (End_x < End_y)')
结果:
print(DF_out)
Start_x End_x Region Start_y End_y ID
0 500 700 A 200 750 1
一个选项是使用pyjanitor中的conditional_join,对于范围连接也是有效的,并且比简单的交叉连接要好:
# pip install pyjanitor
# you can also install the dev version for the latest
# including the ability to use numba for faster performance
# pip install git+https://github.com/pyjanitor-devs/pyjanitor.git
import janitor
import pandas as pd
(DF1
.conditional_join(
DF2,
('Start', 'Start', '>='),
('End', 'End', '<='))
)
left right
Start End Region Start End ID
0 500 700 A 200 750 1
1 850 950 B 800 950 2
对于dev
版本,您也可以选择列:
# pip install git+https://github.com/pyjanitor-devs/pyjanitor.git
import janitor
import pandas as pd
(DF1
.conditional_join(
DF2,
('Start', 'Start', '>='),
('End', 'End', '<='),
df_columns='Region',
right_columns='ID')
)
Region ID
0 A 1
1 B 2
对于dev
版本,如果您安装了numba
,您可以启用它以获得更高的性能。