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

如何高效实现基于艺术家和曲目名称的跨DataFrame流行度字段匹配赋值?

如何高效实现基于艺术家和曲目名称的跨DataFrame流行度字段匹配赋值?

嘿,我太懂你现在的糟心感受了——用双重iterrows()循环遍历50万行和20万行的DataFrame,速度慢到完全无法接受太正常了!这种嵌套的纯Python循环时间复杂度是O(n*m),50万×20万的量级相当于10^10次操作,能跑出来都算幸运的😅。咱们换用pandas原生的矢量化操作和分组优化来解决,速度能提升好几个数量级!

先拆解你的需求核心

你需要把sub_tracks中的popularity字段匹配到df中,匹配条件是:

  • sub_tracks['artiststring']包含在df['artist_name']里
  • sub_tracks['name']包含在df['track_name']里
  • 没有匹配项时,popularity设为0

高效实现方案

方案1:矢量化查询+Apply(比双重循环快100+倍)

先统一字符串大小写避免匹配误差,然后用apply结合pandas的矢量化过滤来替代内层循环:

# 第一步:统一字符串大小写,避免大小写导致的匹配失败
df['artist_name'] = df['artist_name'].str.lower()
df['track_name'] = df['track_name'].str.lower()
sub_tracks['artiststring'] = sub_tracks['artiststring'].str.lower()
sub_tracks['name'] = sub_tracks['name'].str.lower()

# 第二步:定义匹配函数,内部用矢量化过滤
def get_matching_popularity(row):
    # 一次性过滤出符合两个包含条件的记录
    matched_tracks = sub_tracks[
        sub_tracks['artiststring'].str.contains(row['artist_name']) &
        sub_tracks['name'].str.contains(row['track_name'])
    ]
    # 处理多匹配情况:这里取最大流行度,你可以改成取第一个/平均等
    if not matched_tracks.empty:
        return matched_tracks['popularity'].max()
    return 0

# 第三步:批量赋值
df['popularity'] = df.apply(get_matching_popularity, axis=1)

方案2:分组预优化(大数据量下更快)

如果sub_tracks的艺术家重复率很高,可以先按artiststring分组,减少每次查询的数据范围:

# 先统一大小写(同上)
df['artist_name'] = df['artist_name'].str.lower()
df['track_name'] = df['track_name'].str.lower()
sub_tracks['artiststring'] = sub_tracks['artiststring'].str.lower()
sub_tracks['name'] = sub_tracks['name'].str.lower()

# 预按artiststring分组,建立查询字典
artist_track_groups = sub_tracks.groupby('artiststring')

def get_matching_popularity(row):
    # 先筛选出所有包含当前艺术家名称的分组
    matching_artist_keys = [key for key in artist_track_groups.groups if key in row['artist_name']]
    if not matching_artist_keys:
        return 0
    # 合并这些分组,缩小查询范围
    candidate_tracks = pd.concat([artist_track_groups.get_group(key) for key in matching_artist_keys])
    # 再筛选曲目名称匹配的记录
    matched_tracks = candidate_tracks[candidate_tracks['name'].str.contains(row['track_name'])]
    return matched_tracks['popularity'].max() if not matched_tracks.empty else 0

# 批量赋值
df['popularity'] = df.apply(get_matching_popularity, axis=1)

为什么这两种方法更快?

  • 原来的iterrows()是纯Python循环,每一步都要走Python解释器;而pandas的矢量化操作是底层C实现的,执行效率碾压纯Python循环
  • 分组预优化进一步缩小了每次查询的数据量,避免了全表扫描

额外提示

  • 如果你的匹配条件是精确相等而不是包含,那直接用pd.merge()会更快,比如:
    df = df.merge(sub_tracks[['artiststring', 'name', 'popularity']], 
                  left_on=['artist_name', 'track_name'], 
                  right_on=['artiststring', 'name'], 
                  how='left')
    df['popularity'] = df['popularity'].fillna(0)
    
  • 多匹配情况一定要根据业务需求处理:是取第一个匹配项?还是取最高流行度?或者取平均值?

备注:内容来源于stack exchange,提问作者Salman Yusuf Shahiwala

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.23 09:52:44