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

版本对比时首行标签错误问题的排查及替代方案咨询

问题

现有如下结构的DataFrame:

api_spec_id   commit_date             info_version          label
500                2020-07-22           1.1 
500                2020-11-09           1.1 
500                2020-11-16           1.1 
500                2020-11-16           1.1 
500                2020-11-23           1.1 
500                2021-02-01           1.1     
138641             2020-06-25          0.1.0                 major
138641             2020-06-25          0.1.0    
138641             2020-06-27          0.1.0    
138641             2020-06-27          0.1.9                 patch
138641             2020-06-27          0.1.10                patch
138641             2020-06-27          0.1.11                patch
138641             2020-06-27          0.1.13                patch
138641             2020-06-27          0.1.14                patch
138641             2020-06-27          0.1.15                patch
138641             2020-06-28          0.2.0                 minor.patch
138641             2020-06-30          0.2.1                 patch
138641             2020-07-01          0.3.0                 minor.patch
138641             2020-07-08          0.4.0                 minor
138641             2020-07-11          0.5.0                 minor
138641             2020-07-12          0.6.0                 minor

尝试对比连续行的版本并打标签时,出现问题:部分api_spec_id的首行被错误打上标签,实际该行无前置行可对比,标签应为空。

使用的两段处理代码如下:

第一段:正则提取标准语义化版本

pat = r'(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(?:\.(?P<micro>\d+))?'

sem = new['info_version'].str.extract(pat).fillna(0).astype(int)

diff = sem.diff().fillna(0).ne(0)

new['label'] = diff.dot(sem.columns + '.').str.rstrip('.')

第二段:借助Version类解析非标准版本

attrs = ['major', 'minor', 'micro', 'pre', 'post', 'dev', 'local']
def extract_version(ver):
    ver = Version(ver)  
    return pd.Series({attr: getattr(ver, attr) for attr in attrs}, dtype=str)


sem = new['info_version'].agg(extract_version).fillna('').rename(columns={'micro': 'patch'})
diff = sem.ne(sem.shift().fillna(sem.iloc[0]))
new['label'] = diff.dot(sem.columns + '.').str.rstrip('.')

需要排查问题根源,并获取其他计算版本差异的可行方案。

排查思路与解决方案

问题根源

  1. 未按api_spec_id分组处理:当前代码对整个DataFrame做全局版本对比,会跨不同API进行版本对比,导致分组首行错误继承上一个API的版本差异标签。
  2. 首行差异处理错误:两段代码中,首行的diff处理(fillna(0)或fillna(sem.iloc[0]))会让首行和自身对比,产生无意义的差异标签,而非置空。

改进方案

核心思路是按api_spec_id分组,在组内做版本对比,并强制组内首行标签为空。

方案一:正则提取标准语义化版本(改进版)

import pandas as pd

pat = r'(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(?:\.(?P<micro>\d+))?'

def process_group(group):
    # 提取版本字段
    sem = group['info_version'].str.extract(pat).fillna(0).astype(int)
    # 组内计算差异,首行保留NaN
    diff = sem.diff().ne(0)
    # 生成标签,首行转为空字符串
    label = diff.dot(sem.columns + '.').str.rstrip('.')
    label.iloc[0] = ''
    group['label'] = label
    return group

# 按api_spec_id分组处理
new = new.groupby('api_spec_id', group_keys=False).apply(process_group)

方案二:Version类解析非标准版本(改进版)

from packaging.version import Version
import pandas as pd

attrs = ['major', 'minor', 'micro', 'pre', 'post', 'dev', 'local']
def extract_version(ver):
    ver = Version(ver)  
    return pd.Series({attr: getattr(ver, attr) for attr in attrs}, dtype=str)

def process_group(group):
    # 提取版本属性
    sem = group['info_version'].agg(extract_version).fillna('').rename(columns={'micro': 'patch'})
    # 组内对比上一行,首行保留False(无差异)
    diff = sem.ne(sem.shift())
    # 生成标签,首行置空
    label = diff.dot(sem.columns + '.').str.rstrip('.')
    label.iloc[0] = ''
    group['label'] = label
    return group

# 按api_spec_id分组处理
new = new.groupby('api_spec_id', group_keys=False).apply(process_group)

额外优化点

如果commit_date存在乱序,建议在分组后先按commit_date排序,保证版本对比是按时间顺序进行:

def process_group(group):
    group = group.sort_values('commit_date')
    # 后续处理逻辑不变
    ...

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 15:33:15