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

如何基于含逗号分隔ID的列实现DataFrame合规连接与过滤

优化基于逗号分隔PlaceID的DataFrame连接逻辑

需求背景

需要基于AgeGroup和PlaceID连接两个DataFrame,但用户DataFrame的PlaceID以逗号分隔、单个值、null或空值的形式存储在SuitablePlaces列中,需遵循以下规则完成连接:

  • 若SuitablePlaces为null或空值,直接移除该行
  • 单个PlaceID值:匹配AgeGroup+PlaceID组合,成功则新增PlaceName列,否则移除该行
  • 逗号分隔的多个PlaceID:拆分后取第一个匹配AgeGroup+PlaceID组合的记录,新增对应PlaceName,否则移除该行

用户DataFrame结构

NameSexAgeGroupSuitablePlaces
User1Male301,4
User2Female405
User3Male501,3
User4Male401,3,4
User5Female30[null]
User6Female50
User7Male303

地点映射DataFrame结构

AgeGroupPlaceIDPlaceName
301Place1
305Place2
403Place3
405Place4
504Place5
502Place6

现有代码问题

原实现用apply逐行处理,效率低下(尤其是数据量大时),且直接替换了SuitablePlaces列,不符合“新增PlaceName列”的需求。

优化后的地道Pandas实现

采用向量式操作替代逐行循环,利用Pandas内置的explode、merge等优化方法提升效率,同时保留原列并新增目标列:

import pandas as pd

def map_user_places_optimized(user_df, places_df):
    # 复制输入数据避免修改原表
    user_df = user_df.copy()
    places_df = places_df.copy()
    
    # 1. 过滤空值:将空字符串转为NaN后删除对应行
    user_df['SuitablePlaces'] = user_df['SuitablePlaces'].replace('', pd.NA)
    user_df = user_df.dropna(subset=['SuitablePlaces'])
    
    # 2. 拆分逗号分隔的PlaceID为整数列表,保留原始顺序
    user_df['PlaceID_List'] = user_df['SuitablePlaces'].str.split(',')\
        .apply(lambda x: [int(pid.strip()) for pid in x])
    
    # 3. 将列表拆分为多行,保留原行索引用于后续分组取第一个匹配项
    exploded_df = user_df.explode('PlaceID_List', ignore_index=False)\
        .rename(columns={'PlaceID_List': 'PlaceID'})
    
    # 4. 统一数据类型,避免连接时类型不匹配
    exploded_df[['AgeGroup', 'PlaceID']] = exploded_df[['AgeGroup', 'PlaceID']].astype(int)
    places_df[['AgeGroup', 'PlaceID']] = places_df[['AgeGroup', 'PlaceID']].astype(int)
    
    # 5. 内连接地点表,只保留匹配成功的记录
    merged_df = exploded_df.merge(places_df, on=['AgeGroup', 'PlaceID'], how='inner')
    
    # 6. 按原行分组,取第一个匹配的PlaceName(因为explode保留了列表顺序)
    result_df = merged_df.groupby(merged_df.index).first().reset_index(drop=True)
    
    # 7. 整理输出列:保留原用户字段 + 新增的PlaceName
    result_df = result_df[['Name', 'Sex', 'AgeGroup', 'SuitablePlaces', 'PlaceName']]
    
    return result_df

代码说明

  1. 空值过滤:统一处理空字符串和null,确保只保留有效数据
  2. 列表拆分与展开:将逗号分隔的PlaceID转为列表后拆分为多行,保证后续能按顺序匹配
  3. 类型统一:避免因数据类型不一致导致连接失败
  4. 内连接:自动过滤掉匹配失败的记录
  5. 分组取首项:利用原索引分组,取每组第一条记录即实现“第一个匹配”的需求

测试示例

# 构造测试数据
user_data = [
    ['User1', 'Male', 30, '1,4'],
    ['User2', 'Female', 40, '5'],
    ['User3', 'Male', 50, '1,3'],
    ['User4', 'Male', 40, '1,3,4'],
    ['User5', 'Female', 30, pd.NA],
    ['User6', 'Female', 50, ''],
    ['User7', 'Male', 30, '3']
]
user_df = pd.DataFrame(user_data, columns=['Name', 'Sex', 'AgeGroup', 'SuitablePlaces'])

place_data = [
    [30, 1, 'Place1'],
    [30, 5, 'Place2'],
    [40, 3, 'Place3'],
    [40, 5, 'Place4'],
    [50, 4, 'Place5'],
    [50, 2, 'Place6']
]
places_df = pd.DataFrame(place_data, columns=['AgeGroup', 'PlaceID', 'PlaceName'])

# 执行函数并输出结果
result = map_user_places_optimized(user_df, places_df)
print(result)

输出结果

NameSexAgeGroupSuitablePlacesPlaceName
User1Male301,4Place1
User2Female405Place4
User4Male401,3,4Place3

(注:User3、User7因无匹配记录被移除,User5、User6因空值被过滤)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 17:07:15