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

Python中按指定窗口大小对DataFrame指定列进行分组洗牌的实现方法

Python中按指定窗口大小对DataFrame指定列进行分组洗牌的实现方法

嘿,我来帮你搞定这个按指定窗口大小洗牌DataFrame指定列的问题!你要的Pythonic实现其实很简单,核心思路就是把数据按窗口分组,然后对每组的目标列单独打乱,其他列保持原样就行。下面给你两种靠谱的实现方式:

方法一:用groupby + sample实现(简洁优雅)

这种方法利用pandas的分组功能,一行代码就能完成组内洗牌,非常适合日常使用:

import pandas as pd
import numpy as np

def permute(df: pd.DataFrame, window_size: int = 10, modifiable_columns=None) -> pd.DataFrame:
    df_permuted = df.copy()
    # 如果没指定要修改的列,默认用所有列(建议明确指定,避免误改)
    if modifiable_columns is None:
        modifiable_columns = df.columns
    
    # 生成分组键:每window_size行划分为一组
    group_keys = df_permuted.index // window_size
    
    # 对每组的指定列进行随机洗牌,重置索引保证和原组对齐
    df_permuted[modifiable_columns] = df_permuted.groupby(group_keys)[modifiable_columns].apply(
        lambda group: group.sample(frac=1).reset_index(drop=True)
    )
    
    return df_permuted

代码解释:

  • 先复制原DataFrame,避免修改原始数据(这是好习惯哦)
  • group_keys = df.index // window_size 会把索引0-9归为组0,10-19归为组1,以此类推,自动处理最后一组不足window_size的情况
  • sample(frac=1) 是对组内所有行进行无放回的随机打乱,reset_index(drop=True) 是为了让打乱后的行索引和原组的位置对应,不会出现索引错位的问题

方法二:循环遍历窗口(适合大数据集,效率更高)

如果你的DataFrame数据量很大,循环遍历窗口的方式可能会更高效,因为避免了groupby的一些额外开销:

import pandas as pd
import numpy as np

def permute(df: pd.DataFrame, window_size: int = 10, modifiable_columns=None) -> pd.DataFrame:
    df_permuted = df.copy()
    if modifiable_columns is None:
        modifiable_columns = df.columns
    
    total_rows = len(df_permuted)
    # 按窗口大小遍历每一组
    for start_idx in range(0, total_rows, window_size):
        # 计算当前窗口的结束索引,防止最后一组超出数据范围
        end_idx = min(start_idx + window_size, total_rows)
        # 取出当前窗口的目标列数据
        window_data = df_permuted.loc[start_idx:end_idx-1, modifiable_columns]
        # 打乱窗口内的行顺序
        shuffled_window = window_data.sample(frac=1).reset_index(drop=True)
        # 将打乱后的数据放回原位置
        df_permuted.loc[start_idx:end_idx-1, modifiable_columns] = shuffled_window.values
    
    return df_permuted

代码解释:

  • 循环的起始索引每次跳window_size步,确保每个窗口不重叠
  • end_idx = min(start_idx + window_size, total_rows) 处理最后一组行数不足的情况,不会报错
  • 用.values赋值是为了跳过pandas的索引匹配,直接按位置替换,更快更稳妥

测试示例

你可以用下面的代码测试效果,直观看到洗牌前后的差异:

if __name__ == "__main__":
    # 创建测试用的DataFrame
    test_data = {
        '序号': list(range(25)),
        '字母列': [chr(ord('a') + i) for i in range(25)],
        '数值列': np.random.randn(25)
    }
    df = pd.DataFrame(test_data)
    
    # 指定要洗牌的列
    target_cols = ['字母列', '数值列']
    # 调用洗牌函数,窗口大小设为10
    shuffled_df = permute(df, window_size=10, modifiable_columns=target_cols)
    
    print("原数据前15行:")
    print(df.head(15))
    print("\n洗牌后的数据前15行:")
    print(shuffled_df.head(15))

注意事项

  • 两种方法都不会修改原始DataFrame,因为一开始就做了深拷贝
  • 如果不需要洗牌所有列,一定要明确指定modifiable_columns,避免误改不需要变动的列(比如序号列)
  • sample(frac=1) 是完全随机打乱,如果你需要其他洗牌逻辑(比如部分打乱),可以修改这个部分的代码

备注:内容来源于stack exchange,提问作者Invader

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.23 08:37:46