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

Pandas多属性列左连接:标记匹配行及优化连接写法

问题说明

df1 以宽表形式存储产品属性,不同列对应不同属性维度;df2 以长表形式存储属性,所有属性值统一存在Attribute列。原实现通过多次左连接逐列匹配属性,存在重复代码多、无法标记df2匹配行的问题,以下是对应解决方案。

实现方案

1. 核心优化思路

放弃逐属性循环merge的写法,先通过melt将df1从宽表转为长表,仅需一次连接即可完成所有属性的匹配,既减少重复代码,也能在连接过程中直接收集df2的命中行索引,实现匹配状态标记。

2. 完整实现代码

import pandas as pd

# 初始化示例数据
d1 = {"Product": ["product1", "product1", "product2", "product1", "product2", "product1", "product3"], "Store": ["Store1", "Store2", "Store1", "Store1", "Store1", "Store2", "Store2"], "Attribute1": pd.Series(["red", "green", "green", "blue"], index=[0, 2, 5, 6]), "Attribute2": pd.Series(["red", "green", "red"], index=[1, 3, 4])}
df1 = pd.DataFrame(data=d1)

d2 = {"Product": ["product1", "product1", "product2", "product1", "product2", "product1", "product3", "product3", "product2"], "Store": ["Store1", "Store2", "Store1", "Store1", "Store1", "Store2", "Store2", "Store1", "Store2"], "Attribute": ["red", "red", "green", "green", "red", "green", "blue", "blue", "red"], "Package": ["type1", "type2", "type3", "type4", "type5", "type6", "type2", "type4", "type2"]}
df2 = pd.DataFrame(data=d2)

# ========== 配置区:后续新增属性列只需要修改这个列表 ==========
attr_columns = ["Attribute1", "Attribute2"]

# 步骤1:将df1宽表转长表,每个属性单独一行
df1_long = df1.melt(
    id_vars=["Product", "Store"],
    value_vars=attr_columns,
    var_name="attr_type",
    value_name="attr_val"
).dropna(subset=["attr_val"]) # 过滤空属性行,避免无效匹配

# 步骤2:单次连接完成所有属性匹配,同时保留df2原始行号用于标记匹配状态
merge_result = pd.merge(
    df1_long,
    df2.reset_index().rename(columns={"index": "df2_rowid"}),
    how="left",
    left_on=["Product", "Store", "attr_val"],
    right_on=["Product", "Store", "Attribute"]
)

# 解决问题1:给df2新增列标记是否参与过连接匹配
matched_row_ids = set(merge_result["df2_rowid"].dropna().unique())
df2["is_matched"] = df2.index.isin(matched_row_ids)

# 步骤3:聚合拼接Package字段,和原逻辑输出完全对齐
package_agg = merge_result.sort_values("attr_type").groupby(["Product", "Store"])["Package"].agg(
    lambda x: "".join(x.dropna()) # 自动跳过空值,不需要手动替换nan
).reset_index(name="Package")

# 拼回原df1得到最终结果
df3 = pd.merge(df1, package_agg, on=["Product", "Store"], how="left")

3. 方案优势

  • 代码可扩展性强:后续新增属性维度(如Attribute3、Attribute4),仅需将列名加入attr_columns列表即可,不需要重复编写merge、删列逻辑
  • 性能更优:仅需执行一次merge操作,数据量较大时性能提升明显
  • 鲁棒性更好:聚合时自动跳过空值,不需要手动做字符串转义、nan替换操作,避免出现"nan"拼接残留的问题
  • 匹配标记准确:直接通过连接过程中收集的df2原始行号标记匹配状态,不会出现多轮merge后标记冲突、遗漏的问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 21:01:15