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

如何在Python Polars中实现Pandas SQL式的多条件自连接?

问题描述

处理大型DataFrame时遇到内存错误,计划用Python Polars替代Pandas SQL,但无法编写包含两个条件的自连接语法。

数据结构示例:

KeyFieldDateColumn
1234Plumb2020-02-01
1234Plumb2020-03-01
1234Pear2020-04-01

已实现的Pandas SQL版本自连接代码:

import pandas as pd
import datetime as dt
import pandasql as ps

d = {'Key':
          [1234,    1234,   1234,   1234,   1234,   1234,   1234,   
1234,   1234,   1234,   1234,   2456,   2456,   2456,   2456,   2456,   2456,   2456,   2456,   2456,   2456,   2456,   3754,   3754,   3754,   3754,   3754,   3754,   3754,   3754,   3754,   3754,   3754],
         'Field':[
              "Plumb",  "Plumb",    "Pear", "Plumb",    "Orange",   "Pear", "Plumb",    "Plumb",    "Pear", "Apple",    "Plumb",    "Orange",   "Orange",   "Apple",    "Apple",    "Pear", "Apple",    "Plumb",    "Plumb",    "Orange",   "Orange",   "Pear", "Plumb",    "Pear", "Plumb",    "Pear", "Apple",    "Plumb",    "Orange",   "Pear", "Apple",    "Pear", "Apple"],
         'DateColumn':[
              '2020-02-01', '2020-03-01',   '2020-04-01',   '2020-05-01',   '2020-06-01',   '2020-07-01',   '2020-08-01',   '2020-09-01',   '2020-10-01',   '2020-11-01',   '2020-12-01',   '2020-02-01',   '2020-03-01',   '2020-04-01',   '2020-05-01',   '2020-06-01',   '2020-07-01',   '2020-08-01',   '2020-09-01',   '2020-10-01',   '2020-11-01',   '2020-12-01',   '2020-02-01',   '2020-03-01',   '2020-04-01',   '2020-05-01',   '2020-06-01',   '2020-07-01',   '2020-08-01',   '2020-09-01',   '2020-10-01',   '2020-11-01',   '2020-12-01'

     ]}

df = pd.DataFrame(data=d)

df['DateColumn'] = pd.to_datetime(df['DateColumn'])
df['PreviousMonth'] = df['DateColumn'] - pd.DateOffset(months=1)


df_output = ps.sqldf("""
select
a.Key
,a.Field
,b.Field as PreviousField
,a.DateColumn
,b.DateColumn as PreviousDate

from df as a, df as b
where a.Key = b.Key
and b.DateColumn = a.PreviousMonth

""")

print(df_output.head())

该代码输出:

Key   Field                  DateColumn                PreviousDate
0  1234   Plumb  2020-03-01 00:00:00.000000  2020-02-01 00:00:00.000000
1  1234    Pear  2020-04-01 00:00:00.000000  2020-03-01 00:00:00.000000
2  1234   Plumb  2020-05-01 00:00:00.000000  2020-04-01 00:00:00.000000
3  1234  Orange  2020-06-01 00:00:00.000000  2020-05-01 00:00:00.000000
4  1234    Pear  2020-07-01 00:00:00.000000  2020-06-01 00:00:00.000000

尝试了Polars的join语句但不知道添加两个连接条件:

data_output = df.join(df, left_on='Key', right_on='Key')
Polars 多条件自连接实现

在Polars中,实现多条件自连接可以通过以下两种方式:

方式1:使用join方法的多列连接条件

直接将多个连接条件以列表形式传入left_on和right_on参数,同时需要给右侧DataFrame重命名列避免冲突:

import polars as pl

# 转换为Polars DataFrame并处理日期列
pl_df = pl.DataFrame(d)
pl_df = pl_df.with_columns(
    pl.col("DateColumn").str.to_date(),
    PreviousMonth=pl.col("DateColumn").str.to_date().dt.offset_by("-1mo")
)

# 自连接:匹配Key和日期条件
output = pl_df.join(
    pl_df.rename({"Field": "PreviousField", "DateColumn": "PreviousDate"}),
    left_on=["Key", "PreviousMonth"],
    right_on=["Key", "PreviousDate"],
    how="inner"
).select(
    "Key",
    "Field",
    "PreviousField",
    "DateColumn",
    "PreviousDate"
)

print(output.head())

方式2:使用join配合condition参数(Polars >= 0.19.0)

如果需要更灵活的连接条件,可以使用condition参数指定布尔表达式:

import polars as pl

# 转换为Polars DataFrame并处理日期列
pl_df = pl.DataFrame(d)
pl_df = pl_df.with_columns(
    pl.col("DateColumn").str.to_date(),
    PreviousMonth=pl.col("DateColumn").str.to_date().dt.offset_by("-1mo")
)

output = pl_df.join(
    pl_df.rename({"Field": "PreviousField", "DateColumn": "PreviousDate"}),
    on="Key",
    condition=pl.col("PreviousMonth") == pl.col("PreviousDate"),
    how="inner"
).select(
    "Key",
    "Field",
    "PreviousField",
    "DateColumn",
    "PreviousDate"
)

print(output.head())

两种方式都会得到和Pandas SQL版本一致的输出,且Polars的内存效率更高,适合处理大型数据集。

内容的提问来源于stack exchange,提问作者Drthm1456

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 23:20:39