应使用 sample(frac=1) 打乱 dataframe 行序,它保留原始索引(含多级、重复、非连续索引),语义明确且安全;需重置索引时显式调用 reset_index(drop=true)。

用 sample() 而不是 shuffle()
Python 标准库没有 df.shuffle(),Pandas 也没有这个方法——直接调用会报 AttributeError: 'DataFrame' object has no attribute 'shuffle'。正确做法是用 sample(),它默认打乱行顺序且**保留原始索引不变**。
-
sample(n=len(df)):取全部行,等价于全量乱序 -
sample(frac=1):更推荐,语义明确(取 100% 的样本) - 不加
random_state每次结果不同;加了就可复现,调试时建议固定 - 如果原 DataFrame 索引是整数且连续(如
RangeIndex(0, 100)),乱序后索引仍为原值,不会重置为 0~99
为什么 sample(frac=1) 比 iloc[np.random.permutation(len(df))] 更安全?
手动用 np.random.permutation + iloc 确实也能打乱,但容易出错:
安全 Python 代码沙箱:在隔离的沙箱中执行任意 Python 代码,预装 requests、NumPy、pandas 库。返回 stdout、stderr。
- 若原索引非连续(比如删过行,留下
[0, 1, 2, 4, 5]),iloc只按位置取,结果索引看似“重排”,实则丢失了原始索引信息 -
sample()始终基于 label(即索引值)操作,不管索引是否稀疏、是否含字符串、是否重复,都原样保留 -
sample()自动处理空 DataFrame 边界情况;手写 permutation 容易在len(df)==0时抛ValueError
想重置索引?那就显式调用 reset_index()
乱序后若需要连续整数索引(比如后续要按位置切片或对接某些只认 .iloc 的代码),必须主动重置:
-
df.sample(frac=1).reset_index(drop=True):丢弃原索引,生成新RangeIndex -
drop=False(默认)会把原索引作为一列保留,通常不需要 - 注意:
reset_index()是返回新 DataFrame,原地修改需加inplace=True,但不推荐——链式调用更清晰
多级索引和重复索引下 sample() 行为一致吗?
是的,sample() 对索引结构无感,只按行整体抽样:
- 多级索引(
MultiIndex)会被完整保留,每行的层级组合不变 - 若存在重复索引(比如两行都是
idx='A'),sample()仍按行抽,不会去重;抽到哪行,那行的索引值就原样带上 - 唯一要注意的是:如果之后要用
.loc['A']取值,重复索引可能导致返回多行——这不是sample()的问题,而是索引设计本身的问题
sample(frac=1) 是唯一既打乱又忠于索引的设计,其他路径都容易在边界 case 上掉链子。Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










