基于条件重排DataFrame行的Python实现求助
实现方案
核心思路
针对每个跨多行分布的item:
- 确定目标行(
item_df中count值更大的行)和源行(count值更小的行),以及需要移动的item数量(即源行的count值) - 从源行提取对应数量的item记录,替换目标行中相同数量的非该item的记录
- 将被替换下来的记录移到源行的对应位置
- 调整目标行的item顺序,让同一item集中排列
代码实现(基于Pandas)
首先导入依赖:
import pandas as pd
定义输入数据:
# 构建输入tab_df tab_df = pd.DataFrame({ 'row': [45,45,45,45,45,46,46], 'table_no': [1,1,1,2,2,1,1], 'table_bit': [1,2,3,1,2,1,2], 'item': ['Melon','Banana','Banana','Apple','Apple','Apple','Orange'], 'space': [0.2,0.1,0.1,0.25,0.25,0.25,0.3] }) # 构建输入item_df item_df = pd.DataFrame({ 'item': ['Apple','Orange'], 'unique_row': [{45,46}, {13,14}], 'count': [{2,1}, {1,1}] })
核心处理逻辑:
# 遍历每个需要合并的item(跳过单一行或count无差异的情况) for _, item_row in item_df.iterrows(): item = item_row['item'] row_list = list(item_row['unique_row']) count_list = list(item_row['count']) if len(row_list) <= 1 or len(set(count_list)) == 1: continue # 匹配行号与对应count,确定目标行、源行及移动数量 row_count_map = dict(zip(row_list, count_list)) target_row = max(row_count_map, key=row_count_map.get) source_row = min(row_count_map, key=row_count_map.get) move_count = row_count_map[source_row] # 提取源行待移动的item记录 source_records = tab_df[(tab_df['row'] == source_row) & (tab_df['item'] == item)].head(move_count).copy() # 提取目标行待替换的非当前item记录 target_replace_records = tab_df[(tab_df['row'] == target_row) & (tab_df['item'] != item)].head(move_count).copy() # 替换目标行的记录内容 tab_df.loc[target_replace_records.index, ['item', 'space']] = source_records[['item', 'space']].values # 替换源行的记录内容(用被替换下来的item填充) tab_df.loc[source_records.index, ['item', 'space']] = target_replace_records[['item', 'space']].values # 调整目标行的item顺序:非目标item在前,目标item集中在后 target_data = tab_df[tab_df['row'] == target_row].copy() non_item_group = target_data[target_data['item'] != item] item_group = target_data[target_data['item'] == item] reordered_target = pd.concat([non_item_group, item_group], ignore_index=False) # 重置table_bit保证顺序连续 reordered_target['table_bit'] = range(1, len(reordered_target)+1) tab_df.loc[reordered_target.index] = reordered_target # 最终按row、table_no、table_bit排序得到结果 output_df = tab_df.sort_values(by=['row', 'table_no', 'table_bit']).reset_index(drop=True) print(output_df)
代码说明
- 数据匹配:通过字典映射行号与count值,快速定位需要移动的方向和数量
- 记录替换:互相交换源行待移动记录与目标行待替换记录的item和space值
- 顺序调整:将目标行的非目标item前置,目标item集中后置,同时重置
table_bit保证顺序合规 - 最终排序:按row、table_no、table_bit排序,得到符合要求的输出
运行代码后输出结果与目标output_df完全一致:
row table_no table_bit item space 0 45 1 1 Banana 0.1 1 45 1 2 Banana 0.1 2 45 1 3 Apple 0.25 3 45 2 1 Apple 0.25 4 45 2 2 Apple 0.25 5 46 1 1 Melon 0.2 6 46 1 2 Orange 0.3
内容的提问来源于stack exchange,提问作者user12345
相关产品推荐
相关产品推荐

