自学教程 学编程从这里开始

Pandas 抽样与随机数据

承接《Pandas 描述性统计》,本篇讲解 Pandas 样本抽样、分层抽样、随机打乱、随机数据生成、随机种子固定、有放回/无放回抽样,是建模、验证集划分、数据模拟常用功能,保持系列教程统一风格。
前置导入与示例数据

import pandas as pd
import numpy as np

df = pd.DataFrame({
    "region": ["华东","华东","华南","华南","华北","华北","华东","华南","华北","华东"],
    "cate": ["手机","电脑","手机","电脑","手机","电脑","手机","电脑","手机","电脑"],
    "sales": [1200, 800, 1500, 950, 1100, 780, 1350, 1020, 960, 1420],
    "profit": [180, 120, 220, 140, 160, 110, 195, 150, 132, 176]
})
print(df)

一、sample 基础抽样函数

df.sample() 是 Pandas 内置抽样方法,支持按数量、按比例抽样,控制是否放回。

df.sample(
    n=None,
    frac=None,
    replace=False,
    random_state=None,
    axis=0,
    weights=None,
    ignore_index=False
)
  • n:抽样行数(整数)
  • frac:抽样比例,0~1
  • replace=False:无放回抽样;replace=True:有放回抽样(允许重复抽到同一行)
  • random_state:随机种子,固定结果,复现实验
  • ignore_index=True:抽样后重置索引

1. 指定行数抽样

# 随机抽取3行
sample_n = df.sample(n=3, random_state=42)
print(sample_n)

2. 按比例抽样

# 抽取30%的数据
sample_frac = df.sample(frac=0.3, random_state=42)
print(sample_frac)

3. 有放回抽样(可重复)

适合 bootstrap 自助抽样

sample_replace = df.sample(n=10, replace=True, random_state=42)

4. 打乱整张表(frac=1)

经常用来做数据集洗牌

df_shuffle = df.sample(frac=1, random_state=42, ignore_index=True)

二、权重抽样 weights

按权重概率抽样,权重越大,被抽到概率越高

# 权重列,sales越大,被抽到概率越高
sample_weight = df.sample(n=4, weights="sales", random_state=42)
print(sample_weight)

weights 也可以直接传入一维数组:

df.sample(n=3, weights=[0.1,0.1,0.2,0.2,0.05,0.05,0.1,0.1,0.05,0.05])

三、分层抽样(业务高频)

简单随机抽样容易导致小类别样本抽不到,分层抽样保证每个分组都抽到样本。
方案:groupby + sample

# 按region分层,每个地区抽2条
strat_sample = df.groupby("region", group_keys=False).apply(
    lambda x: x.sample(n=2, random_state=42)
)
print(strat_sample)

按比例分层:每个分组抽取该组 50%

strat_frac = df.groupby("region", group_keys=False).apply(
    lambda x: x.sample(frac=0.5, random_state=42)
)

注意:group_keys=False,避免生成多余的外层索引

四、划分训练集、测试集

简易划分(不推荐复杂建模,复杂场景用sklearn)

# 7:3划分
train = df.sample(frac=0.7, random_state=42)
test = df.drop(train.index)
print("训练集数量:", len(train))
print("测试集数量:", len(test))

分层划分版本(保证地区分布一致)

def strat_split(df, group_col, test_ratio=0.3):
    test = df.groupby(group_col, group_keys=False).apply(
        lambda x: x.sample(frac=test_ratio, random_state=42)
    )
    train = df.drop(test.index)
    return train, test

train_df, test_df = strat_split(df, "region", 0.3)

五、np.random 配合 Pandas 生成随机数据

5.1 生成随机整数

df["rand_int"] = np.random.randint(100, 500, size=len(df))

5.2 0~1均匀随机数

df["rand_uniform"] = np.random.rand(len(df))

5.3 正态分布随机数

df["rand_norm"] = np.random.normal(loc=100, scale=10, size=len(df))

5.4 随机选择指定候选值

df["rand_promo"] = np.random.choice([0,1], size=len(df), p=[0.7,0.3])

p 是每个选项的概率之和必须=1

六、固定随机种子

如果不设置 random_state,每次运行抽样结果不一样。
两种固定方式:

# 方式1:sample内指定random_state(推荐,局部生效)
df.sample(n=3, random_state=42)

# 方式2:全局numpy种子(全局生效)
np.random.seed(42)

建议优先写在 sample 参数里,避免全局污染其他随机逻辑。

七、随机排序、随机取列

axis=1 对列抽样

# 随机挑选2列
col_sample = df.sample(n=2, axis=1)
print(col_sample)

八、抽样校验

抽样后检查分布是否和原数据接近

# 原分布
print(df["region"].value_counts(normalize=True))
# 抽样样本分布
print(sample_frac["region"].value_counts(normalize=True))

九、高频坑清单

  1. 样本量大于分组行数,无放回抽样直接报错,需要 replace=True
  2. 分层抽样忘记 group_keys=False,结果多出一层索引
  3. 划分训练测试集只用简单sample,类别不平衡(小类别全部进训练集)
  4. 权重存在0、负数,weights 报错;权重会自动归一化,但不能为负
  5. 多次抽样不设置random_state,结果不可复现,调试困难
  6. frac=1 洗牌后索引不变,记得 ignore_index=True
  7. np.random.seed 全局种子,和 sample 的 random_state 是两套独立随机器

十、综合实战模板

def simple_sample(df, n=None, frac=None, seed=42):
    """简单随机抽样"""
    return df.sample(n=n, frac=frac, random_state=seed, ignore_index=True)

def stratified_sample(df, group_col, n_per_group=None, frac=None, seed=42):
    """分层抽样,每组固定数量或者固定比例"""
    if n_per_group is not None:
        fn = lambda x: x.sample(n=n_per_group, random_state=seed)
    else:
        fn = lambda x: x.sample(frac=frac, random_state=seed)
    return df.groupby(group_col, group_keys=False).apply(fn)

# 调用
sample_strat = stratified_sample(df, group_col="region", n_per_group=2)
print(sample_strat)

十一、速查表

需求写法
随机抽N行sample(n=5)
抽取20%数据sample(frac=0.2)
洗牌打乱整张表sample(frac=1, ignore_index=True)
有放回自助抽样sample(replace=True)
按字段概率加权抽样sample(weights=”col”)
每个分组都抽到样本groupby + sample
固定随机结果random_state=42
标签:

0 条笔记