HOWTO · Pandas

如何对 Pandas 中的 DataFrame 行随机排序

可以使用 pandas 的 `pandas.DataFrame.sample()`、NumPy 的 `numpy.random.permutation()` 或 scikit-learn 的 `sklearn.utils.shuffle()`,随机打乱 pandas DataFrame 的所有行。

本页内容

要重新排列 pandas DataFrame 中的所有行,请调用 sample(frac=1)。frac 参数表示抽取包含全部行的样本,axis=0 表示选择行(这是默认值)。采样会返回一个新的 DataFrame,不会改变原对象的排列顺序。行顺序是随机的,因此多次调用可能得到不同的排列。使用默认采样行为时,源数据中的每一行都会恰好出现一次,且各列的值仍保持在同一行中。返回结果会保留原有的索引标签,除非你重置索引。自定义索引与默认整数索引一样会被保留。

使用 pandas.DataFrame.sample() 打乱所有 DataFrame 行

如果 DataFrame 已经是 pandas 对象,pandas.DataFrame.sample() 是最直接的选择。此示例会创建一个小表,并打印打乱顺序后的副本。示例固定了 random_state,以展示一种具体排列;如果希望每次调用都生成新的排列,请省略该参数。

运行此示例。示例代码以及其中显示的标签和输出仍为英文:

import pandas as pd

df = pd.DataFrame({
    "item": ["pear", "plum", "lime", "fig"],
    "quantity": [4, 2, 5, 1],
})
shuffled = df.sample(frac=1, random_state=1)
print(shuffled)

此示例的输出:

   item  quantity
3   fig         1
2  lime         5
0  pear         4
1  plum         2

赋值操作会保留原始 df,其行顺序不会改变。如果希望明确表明选择的是行,可以显式指定 axis=0;省略它时,行为仍然是按行操作。

打乱行后重置索引

打乱后的结果会保留源行的标签,因此索引看起来可能不连续。若要将这些标签替换为 0, 1, 2, ...,可以在采样后接上 reset_index(drop=True):

shuffled = df.sample(frac=1).reset_index(drop=True)

reset_index() 通常会把旧索引保留为一列。设置 drop=True 则会丢弃这些旧标签。若后续代码需要从头开始的连续索引,请使用此选项;若原始标签用于标识记录且应继续与记录关联,则省略它。

使用 numpy.random.permutation() 打乱行

NumPy 还提供了另一种按随机顺序选择行的方法。numpy.random.permutation() 会打乱一组行位置;将这些位置传给 df.iloc[...],即可选出对应的完整行。例如,核心表达式是 df.iloc[numpy.random.permutation(len(df))]。这种按位置选择的方式不受 DataFrame 索引标签的影响。操作会按照生成的位置顺序返回行,多次调用的顺序可能不同。只有在需要新的连续标签时,才重置结果的索引。

使用 sklearn.utils.shuffle() 打乱行

如果项目已经使用 scikit-learn,sklearn.utils.shuffle(df) 会以打乱后的顺序返回各行,同时保留每行各列之间的对应关系。它是 pandas 采样之外的另一种选择,需要安装 scikit-learn 软件包;如果运行程序的环境中尚未安装,请在该环境中安装。若工作流程只使用 pandas,df.sample(frac=1) 无需增加此依赖。无论使用哪种方法,都要保留返回的 DataFrame(或将其重新赋值给 df),才能使用新的行顺序。这些方法打乱的是完整行,不会打乱行内的值,也不会只选择表格的一部分。