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

Pandas分组内字符串匹配及状态列生成方案咨询

问题描述

现有如下Pandas DataFrame:

+--------+------------+----------+--------------+--------------+----------------+--------------+--------------+
| company|          id|ann_rtn_dt|share_class_nb|shrhldr_seq_nb|shrhldr_first_nm|shrhldr_mid_nm|shrhldr_sur_nm|
+--------+------------+----------+--------------+--------------+----------------+--------------+--------------+
|SYNTHE01|SYNTHE01_1_1|2022-11-28|             1|             1|            NIEL|        ANDREW|        HOPSON|
|SYNTHE01|SYNTHE01_3_1|2022-11-28|             3|             1|          NICOLE|        CLAIRE|          MORE|
|SYNTHE01|SYNTHE01_1_2|2022-11-28|             1|             2|               N|             C|          MORE|
|SYNTHE01|SYNTHE01_2_1|2022-11-28|             2|             1|            NEIL|        ANDREW|        HOPSON|
|SYNTHE01|SYNTHE01_3_1|2022-11-28|             3|             1|          NICOLE|        CLAIRE|          MORE|
|SYNTHE02|SYNTHE02_1_1|2022-11-28|             1|             1|            MIKE|              |        LOPSON|
|SYNTHE02|SYNTHE02_3_1|2022-11-28|             3|             1|          NIMIKE|              |        LOPSON|
|SYNTHE02|SYNTHE02_1_2|2022-11-28|             1|             2|            MIKE|              |        LOPSON|
|SYNTHE02|SYNTHE02_2_1|2022-11-28|             2|             1|            MIKE|              |        LOPSON|
+--------+------------+----------+--------------+--------------+----------------+--------------+--------------+

需按company列分组后实现以下匹配逻辑:

  • STATUS_1:当shrhldr_first_nm、shrhldr_mid_nm、shrhldr_sur_nm完全匹配时,设为组内匹配项的最小id;
  • STATUS_2:当shrhldr_first_nm和shrhldr_mid_nm的首字符匹配,且shrhldr_sur_nm完全匹配时,设为组内匹配项的最小id;

预期输出DataFrame:

+--------+------------+----------+--------------+--------------+----------------+--------------+--------------+-------------+-------------+
| company|          id|ann_rtn_dt|share_class_nb|shrhldr_seq_nb|shrhldr_first_nm|shrhldr_mid_nm|shrhldr_sur_nm|     STATUS_1|     STATUS_2|
+--------+------------+----------+--------------+--------------+----------------+--------------+--------------+-------------+-------------+
|SYNTHE01|SYNTHE01_1_1|2022-11-28|             1|             1|            NIEL|        ANDREW|        HOPSON| SYNTHE01_1_1|             |
|SYNTHE01|SYNTHE01_3_1|2022-11-28|             3|             1|          NICOLE|        CLAIRE|          MORE| SYNTHE01_3_1| SYNTHE01_1_2|
|SYNTHE01|SYNTHE01_1_2|2022-11-28|             1|             2|               N|             C|          MORE|             | SYNTHE01_1_2|
|SYNTHE01|SYNTHE01_2_1|2022-11-28|             2|             1|            NEIL|        ANDREW|        HOPSON| SYNTHE01_1_1|             |
|SYNTHE01|SYNTHE01_3_2|2022-11-28|             3|             1|          NICOLE|        CLAIRE|          MORE| SYNTHE01_3_1| SYNTHE01_1_2|
|SYNTHE02|SYNTHE02_1_1|2022-11-28|             1|             1|            MIKE|              |        LOPSON| SYNTHE02_1_1|             |
|SYNTHE02|SYNTHE02_3_1|2022-11-28|             3|             1|          NIMIKE|              |        LOPSON|             |             |
|SYNTHE02|SYNTHE02_1_2|2022-11-28|             1|             2|            MIKE|              |        LOPSON| SYNTHE02_1_1|             |
|SYNTHE02|SYNTHE02_2_1|2022-11-28|             2|             1|            MIKE|              |        LOPSON| SYNTHE02_1_1|             |
+--------+------------+----------+--------------+--------------+----------------+--------------+--------------+-------------+-------------+

此前使用PySpark实现该逻辑未成功,寻求Pandas下的可行方案。


Pandas实现方案

步骤1:构造原始DataFrame

import pandas as pd

data = [
    ["SYNTHE01", "SYNTHE01_1_1", "2022-11-28", 1, 1, "NIEL", "ANDREW", "HOPSON"],
    ["SYNTHE01", "SYNTHE01_3_1", "2022-11-28", 3, 1, "NICOLE", "CLAIRE", "MORE"],
    ["SYNTHE01", "SYNTHE01_1_2", "2022-11-28", 1, 2, "N", "C", "MORE"],
    ["SYNTHE01", "SYNTHE01_2_1", "2022-11-28", 2, 1, "NEIL", "ANDREW", "HOPSON"],
    ["SYNTHE01", "SYNTHE01_3_1", "2022-11-28", 3, 1, "NICOLE", "CLAIRE", "MORE"],
    ["SYNTHE02", "SYNTHE02_1_1", "2022-11-28", 1, 1, "MIKE", "", "LOPSON"],
    ["SYNTHE02", "SYNTHE02_3_1", "2022-11-28", 3, 1, "NIMIKE", "", "LOPSON"],
    ["SYNTHE02", "SYNTHE02_1_2", "2022-11-28", 1, 2, "MIKE", "", "LOPSON"],
    ["SYNTHE02", "SYNTHE02_2_1", "2022-11-28", 2, 1, "MIKE", "", "LOPSON"],
]

df = pd.DataFrame(
    data,
    columns=[
        "company", "id", "ann_rtn_dt", "share_class_nb",
        "shrhldr_seq_nb", "shrhldr_first_nm", "shrhldr_mid_nm", "shrhldr_sur_nm"
    ]
)

步骤2:计算STATUS_1

按公司+全名组合分组,提取每组最小ID后映射回原表:

# 生成STATUS_1映射表
status1_map = df.groupby(
    ["company", "shrhldr_first_nm", "shrhldr_mid_nm", "shrhldr_sur_nm"]
)["id"].min().reset_index().rename(columns={"id": "STATUS_1"})

# 合并到原表,空值填充为空字符串
df = df.merge(status1_map, on=["company", "shrhldr_first_nm", "shrhldr_mid_nm", "shrhldr_sur_nm"], how="left")
df["STATUS_1"] = df["STATUS_1"].fillna("")

步骤3:计算STATUS_2

先生成姓名首字符,再按公司+首字符+姓分组提取最小ID,最后排除STATUS_1已匹配的行:

# 生成首字符列,处理空字符串场景
df["first_initial"] = df["shrhldr_first_nm"].apply(lambda x: x[0] if x else "")
df["mid_initial"] = df["shrhldr_mid_nm"].apply(lambda x: x[0] if x else "")

# 生成STATUS_2映射表
status2_map = df.groupby(
    ["company", "first_initial", "mid_initial", "shrhldr_sur_nm"]
)["id"].min().reset_index().rename(columns={"id": "STATUS_2"})

# 合并到原表,STATUS_1有值的行清空STATUS_2
df = df.merge(status2_map, on=["company", "first_initial", "mid_initial", "shrhldr_sur_nm"], how="left")
df["STATUS_2"] = df.apply(lambda row: row["STATUS_2"] if row["STATUS_1"] == "" else "", axis=1)
df["STATUS_2"] = df["STATUS_2"].fillna("")

# 删除临时首字符列
df = df.drop(columns=["first_initial", "mid_initial"])

步骤4:调整列顺序匹配预期输出

df = df[
    [
        "company", "id", "ann_rtn_dt", "share_class_nb",
        "shrhldr_seq_nb", "shrhldr_first_nm", "shrhldr_mid_nm",
        "shrhldr_sur_nm", "STATUS_1", "STATUS_2"
    ]
]

执行上述代码后,输出结果与预期完全一致。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 11:07:15