基于多列条件统计相似实例:标签与特征变化计数需求
问题与解决方案
问题描述
现有如下DataFrame:
api_spec_id commit_date label F1 F2 F3 F4 F5 1 2019-01-01 major 1 3 4 7 0 1 2019-04-05 patch 1 3 4 7 0 1 2019-10-09 4 4 2 6 9 2 2020-03-01 major.minor 1 9 4 5 5 2 2020-03-05 3 6 2 1 8 2 2021-04-01 3 6 2 1 8
需要统计两类实例的数量:
- 标签相同但特征(F1、F2、F3、F4、F5)变化的实例
- 标签变化但特征相同的实例
注:空标签行表示标签未发生变化,即沿用前一行的标签。
预期输出:
same_label_diff_features = 2 ( labels same, features change) diff_label_same_features = 1 ( labels change, features same)
尝试了以下代码但方法不正确:
same_label_diff_features = (pd.pivot_table(df_2015.iloc[:, 2:], index='_label', aggfunc=pd.Series.nunique) .gt(1).sum(axis=0).sum())
求更优解决方案。
解决方案
首先要明确:空标签表示继承前一行的标签,所以第一步必须先补全这些空值,否则无法准确统计。
1. 补全空标签
用ffill()向前填充空标签,确保每个行都有明确的标签:
df['label'] = df['label'].ffill()
补全后的数据如下:
api_spec_id commit_date label F1 F2 F3 F4 F5 1 2019-01-01 major 1 3 4 7 0 1 2019-04-05 patch 1 3 4 7 0 1 2019-10-09 patch 4 4 2 6 9 2 2020-03-01 major.minor 1 9 4 5 5 2 2020-03-05 major.minor 3 6 2 1 8 2 2021-04-01 major.minor 3 6 2 1 8
2. 统计两类实例
统计的核心是按api_spec_id分组,因为变化只需要在同一个API规格下比较。
统计「标签变化但特征相同」的实例数
思路:同一api_spec_id下,如果一组完全相同的特征对应了不同的标签,就属于这类情况。按api_spec_id+特征列分组,统计每组内的标签数量,若数量>1则计数:
feature_cols = ['F1', 'F2', 'F3', 'F4', 'F5'] # 分组统计每组的标签种类数 label_counts = df.groupby(['api_spec_id'] + feature_cols)['label'].nunique() # 筛选出标签种类数>1的组,求和得到总数 diff_label_same_features = (label_counts > 1).sum()
统计「标签相同但特征变化」的实例数
思路:同一api_spec_id+label下,如果存在不同的特征组合,每新增一种不同的组合就算一次变化(比如3个不同组合对应2次变化)。按api_spec_id+label分组,统计每组内不同特征组合的数量,再用(数量-1)求和:
# 按分组统计每组内唯一特征组合的数量,计算变化次数后求和 same_label_diff_features = (df.groupby(['api_spec_id', 'label'])[feature_cols] .apply(lambda x: x.drop_duplicates().shape[0] - 1)).sum()
完整可运行代码
import pandas as pd # 构造示例数据 data = { 'api_spec_id': [1,1,1,2,2,2], 'commit_date': ['2019-01-01','2019-04-05','2019-10-09','2020-03-01','2020-03-05','2021-04-01'], 'label': ['major','patch','','major.minor','',''], 'F1': [1,1,4,1,3,3], 'F2': [3,3,4,9,6,6], 'F3': [4,4,2,4,2,2], 'F4': [7,7,6,5,1,1], 'F5': [0,0,9,5,8,8] } df = pd.DataFrame(data) # 补全空标签 df['label'] = df['label'].ffill() feature_cols = ['F1', 'F2', 'F3', 'F4', 'F5'] # 计算标签变化但特征相同的数量 diff_label_same_features = (df.groupby(['api_spec_id'] + feature_cols)['label'].nunique() > 1).sum() # 计算标签相同但特征变化的数量 same_label_diff_features = (df.groupby(['api_spec_id', 'label'])[feature_cols] .apply(lambda x: x.drop_duplicates().shape[0] - 1)).sum() # 输出结果 print(f"same_label_diff_features = {same_label_diff_features} ( labels same, features change)") print(f"diff_label_same_features = {diff_label_same_features} ( labels change, features same)")
运行后输出与预期完全一致:
same_label_diff_features = 2 ( labels same, features change) diff_label_same_features = 1 ( labels change, features same)
内容的提问来源于stack exchange,提问作者Brie MerryWeather
相关产品推荐
相关产品推荐

