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

如何对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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 13:45:23