You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Pandas中执行带非相等条件的单步合并(类SQL连接)

如何在Pandas中执行带非相等条件的单步合并(类SQL连接)

假设我们有两个需要合并的DataFrame:

import pandas as pd

df1 = pd.DataFrame()
df1["key"] = ["a", "b", "c"]
df1["low"] = [0, 1, 2]
df1["high"] = [2, 4, 6]

df2 = pd.DataFrame()
df2["key"] = ["a", "a", "a", "b", "b", "c"]
df2["value"] = [1, 2, 3, 2, 5, 0]

print(f"df1:\n{df1}")
print(f"df2:\n{df2}")

输出:

df1:
  key  low  high
0   a    0     2
1   b    1     4
2   c    2     6
df2:
  key  value
0   a      1
1   a      2
2   a      3
3   b      2
4   b      5
5   c      0

如果我想要合并这两个DataFrame,只保留key匹配且value在low和high之间的行,我知道可以分两步完成:

df = df1.merge(df2, how="inner", on="key")
df = df.loc[(df["value"] >= df["low"]) & (df["value"] <= df["high"])]
print(f"df:\n{df}")

输出:

df:
  key  low  high  value
0   a    0     2      1
1   a    0     2      2
3   b    1     4      2

但如果DataFrame很大的话,这种方法可能不实用,因为第一步的合并操作可能会耗时很久(详情见下文)。

在SQL中,我们可以很轻松地用如下查询实现这种连接:

SELECT
    df1.key,
    df1.low,
    df1.high,
    df2.value
FROM df1
INNER JOIN df2
ON
    df1.key = df2.key AND
    df2.value BETWEEN df1.low AND df1.high

有没有办法在Python中用一步操作完成这种合并?

编辑1:我需要的是不需要安装pandas之外的额外依赖(比如pyjanitor或其他模块)的解决方案。

编辑2:这里的“一步”指的是用单个pandas操作完成合并,而不是把两个操作(比如.merge和.loc)写在同一行。


为什么不直接链式调用Pandas操作?

有些人会给出类似这样的解决方案:

df = df1.merge(df2, how="inner", on="key").loc[lambda r: (r["value"] >= r["low"]) & (r["value"] <= r["high"])]

这个方法虽然能运行,但在数据量较大时并不实用——因为它会先合并两个DataFrame,再进行筛选操作。如果DataFrame很大,df1.merge(df2, how="inner", on="key")的计算成本会非常高。

举个例子,我们给原来的df1和df2添加更多行:

import pandas as pd
import random
random.seed(42)

add_rows = 10

df1 = pd.DataFrame()
df1["key"] = ["a", "b", "c"] + random.choices(["a", "b", "c"], k=add_rows)
df1["low"] = [0, 1, 2] + list(range(100, 100 + add_rows))
df1["high"] = df1["low"] + 2

df2 = pd.DataFrame()
df2["key"] = ["a", "a", "a", "b", "b", "c"] + random.choices(["a", "b", "c"], k=add_rows)
df2["value"] = [1, 2, 3, 2, 5, 0] + list(range(-add_rows, 0))

print(f"df1:\n{df1}")
print(f"df2:\n{df2}")

输出:

df1:
   key  low  high
0    a    0     2
1    b    1     3
2    c    2     4
3    b  100   102
4    a  101   103
5    a  102   104
6    a  103   105
7    c  104   106
8    c  105   107
9    c  106   108
10   a  107   109
11   b  108   110
12   a  109   111
df2:
   key  value
0    a      1
1    a      2
2    a      3
3    b      2
4    b      5
5    c      0
6    a    -10
7    b     -9
8    a     -8
9    a     -7
10   b     -6
11   b     -5
12   a     -4
13   b     -3
14   c     -2
15   a     -1

注意到df2的value列全是负数,而df1的low和high列全是正数,所以不管添加多少行,最终结果始终只有3行。

  • 当添加10行时,df1.merge(df2, how="inner", on="key")会生成74行,整个链式操作在我的机器上耗时约0.005秒。
  • 当添加1000行时,合并后的DataFrame有33.6万行,最终结果(保持不变)耗时约0.03秒。
  • 当添加10000行时,合并后的DataFrame有3330万行,操作耗时1.03秒,甚至可能导致笔记本崩溃。

我们需要的是一种在合并过程中就完成筛选的方法,避免生成不必要的中间大表。


备注:内容来源于stack exchange,提问作者gasbag_1

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 08:48:10