如何对Pandas DataFrame按order列分组后的每个子集执行规则化随机排序?
问题描述
我针对DataFrame的某列制定了如下排序规则:当特定列(weight列)连续两行数值的比值处于0.7至1.3区间内时,有50%的概率交换这两行的位置。我已编写了对应的实现函数:
def randomized_sort(df): """ :param df: dataframe :return: sorted dataframe based on the condition """ length = len(df) if len(df) % 2 == 0 else len(df) - 1 for i in range(0, length, 2): if random.random() < 0.5: if (0.7 < (df.iloc[i, :].weight) / (df.iloc[i + 1, :].weight) < 1.3): a, b = df.iloc[i, :].copy(), df.iloc[i + 1, :].copy() df.iloc[i, :], df.iloc[i + 1, :] = b, a return df
现在我有一个新的DataFrame,需要对按order列分组后的每个子集执行上述排序操作,请问该如何实现?
实现方案
你可以借助Pandas的groupby+apply组合,对每个order分组后的子集单独调用自定义排序函数,最终合并所有分组的结果。具体实现如下:
优化后的排序函数(避免修改原数据)
先给你的函数做个小优化:先复制输入的DataFrame再操作,防止污染原始数据,同时简化行交换逻辑:
import pandas as pd import random def randomized_sort(df): """ :param df: dataframe :return: sorted dataframe based on the condition """ df_copy = df.copy() length = len(df_copy) if len(df_copy) % 2 == 0 else len(df_copy) - 1 for i in range(0, length, 2): if random.random() < 0.5: weight_ratio = df_copy.iloc[i]["weight"] / df_copy.iloc[i+1]["weight"] if 0.7 < weight_ratio < 1.3: # 直接切片交换两行 df_copy.iloc[i:i+2] = df_copy.iloc[i:i+2][::-1].values return df_copy
分组执行排序
假设你的目标DataFrame名为new_df,按order列分组并应用排序函数:
# 按order分组,对每个分组应用排序函数,group_keys=False避免分组键混入索引 result_df = new_df.groupby("order", group_keys=False).apply(randomized_sort) # 可选:重置为连续整数索引 result_df = result_df.reset_index(drop=True)
关键说明
groupby("order")会将DataFrame按order列的唯一值拆分为多个子集apply(randomized_sort)会对每个子集单独执行你的排序逻辑group_keys=False参数可以让输出的DataFrame结构更简洁,不会保留分组的层级索引
内容的提问来源于stack exchange,提问作者mars
相关产品推荐
相关产品推荐

