基于动态条件对DataFrame数据进行分组打标签的技术求助
基于动态条件为DataFrame用户批量打标签的解决方案
我来帮你搞定这个按动态规则给DataFrame用户分组打标签的需求,咱们先理清楚需求细节,再给出可运行的实现代码。
初始数据集(df3)
首先是你提供的第一个测试数据集:
import pandas as pd df3 = pd.DataFrame({ 'first_name': ['John', 'John', 'Jane', 'Jane', 'Jane','Marry', 'Victoria', 'Gabriel', 'John'], 'id': [1, 1, 2, 2, 2, 3, 4, 5, 1], 'age': [30, 30, 25, 25, 25, 30, 45, 15, 30], 'group': [0, 0, 0, 0, 0, 0, 0, 0, 0], 'product_type': [1, 1, 2, 1, 2, 1, 2, 1, 2], 'quantity': [10, 15, 10, 10, 15, 30, 30, 10, 10] }) df3['agemore'] = (df3['age'] > 20)
核心分组规则
你需要按照以下逻辑为用户(按id区分)标记group值:
- 优先选取当前
group=0中id最小的用户,先将其所有行标记为当前分组号(初始为1); - 提取该用户
agemore=True、按product_type分组后的排序后quantity列表作为匹配特征; - 查找所有未分组的用户,若该用户满足
agemore=True,且其某类product_type对应的排序后quantity列表与目标用户的任意一个特征列表匹配,则将该用户也标记为当前分组号; - 递增分组号,重复上述步骤,直到所有用户都完成分组。
(注:根据你给出的示例,id=1的product_type=1对应quantity[10,15],id=2的product_type=2对应quantity[10,15],二者匹配,因此归为同一组)
预期输出(df4)
最终分组后的结果应该是这样的:
df4 = pd.DataFrame({ 'first_name': ['John', 'John', 'Jane', 'Jane', 'Jane','Marry', 'Victoria', 'Gabriel', 'John'], 'id': [1, 1, 2, 2, 2, 3, 4, 5, 1], 'age': [30, 30, 25, 25, 25, 30, 45, 15, 30], 'group': [1, 1, 1, 1, 1, 2, 2, 3, 1], 'product_type': [1, 1, 2, 1, 2, 1, 2, 1, 2], 'quantity': [10, 15, 10, 10, 15, 30, 30, 10, 10] })
第二个测试数据集(set2)
你还提供了第二个测试数据集用于验证:
import pandas as pd data = pd.DataFrame({ 'first_name': ['John', 'John', 'Jane', 'Jane', 'Jane','Marry', 'Victoria', 'Gabriel', 'John'], 'id': [1, 1, 2, 2, 2, 3, 4, 5, 1], 'age': [30, 30, 25, 25, 25, 30, 45, 15, 3], 'group': [0, 0, 0, 0, 0, 0, 0, 0, 0], 'product_type': [1, 1, 2, 1, 2, 1, 2, 1, 1], 'quantity': [10, 15, 10, 10, 15, 30, 30, 10, 10] }) data['agemore'] = (data['age'] > 20)
实现代码
下面是完全符合需求的Python代码,包含详细注释:
def assign_dynamic_groups(df): # 复制原数据,避免修改原始输入 df_processed = df.copy() current_group_num = 1 # 获取所有唯一用户id,按升序排列,方便后续取最小未分组id all_unique_ids = sorted(df_processed['id'].unique()) while True: # 筛选出当前未分组的用户id(group=0) ungrouped_ids = [user_id for user_id in all_unique_ids if df_processed[df_processed['id'] == user_id]['group'].iloc[0] == 0] if not ungrouped_ids: break # 所有用户都已分组,退出循环 # 取当前未分组中id最小的用户作为目标用户 target_id = min(ungrouped_ids) target_user_data = df_processed[df_processed['id'] == target_id] # 标记目标用户为当前分组 df_processed.loc[df_processed['id'] == target_id, 'group'] = current_group_num # 提取目标用户的匹配特征:agemore=True时,按product_type分组的排序后quantity列表 target_features = (target_user_data[target_user_data['agemore'] == True] .groupby('product_type')['quantity'] .apply(lambda x: sorted(x.tolist())) .to_dict()) target_quant_lists = list(target_features.values()) # 遍历其他未分组用户,进行特征匹配 for compare_id in ungrouped_ids[1:]: compare_user_data = df_processed[df_processed['id'] == compare_id] # 跳过agemore全为False的用户(按规则要求agemore=True) if not compare_user_data['agemore'].any(): continue # 提取待匹配用户的特征 compare_features = (compare_user_data[compare_user_data['agemore'] == True] .groupby('product_type')['quantity'] .apply(lambda x: sorted(x.tolist())) .to_dict()) compare_quant_lists = list(compare_features.values()) # 检查是否存在匹配的quantity列表 if any(quant_list in compare_quant_lists for quant_list in target_quant_lists): # 匹配成功,标记为当前分组 df_processed.loc[df_processed['id'] == compare_id, 'group'] = current_group_num # 分组号递增,处理下一组 current_group_num += 1 return df_processed # 测试第一个数据集 df4 = assign_dynamic_groups(df3) print("第一个数据集分组结果:") print(df4) # 测试第二个数据集 data_grouped = assign_dynamic_groups(data) print("\n第二个数据集分组结果:") print(data_grouped)
代码关键点说明
- 数据安全:先复制原数据,避免修改原始输入;
- 循环逻辑:持续找到最小未分组用户,直到所有用户完成分组;
- 特征提取:针对
agemore=True的行,按product_type提取排序后的quantity列表,确保匹配不受顺序影响; - 匹配规则:检查待匹配用户是否有任意一组quantity列表与目标用户的特征列表一致,同时满足
agemore=True的条件。
内容的提问来源于stack exchange,提问作者rm1991
相关产品推荐
相关产品推荐

