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

如何用PySpark实现满足多列比例要求的10万行分层抽样?

PySpark实现满足双重维度比例约束的随机抽样

要实现同时满足OCCUPA_ID和DIG_LABEL双重比例的10万行抽样,核心思路是先计算两个字段交叉组合的目标抽样量,再针对每个组合单独抽样后合并,具体步骤如下:

1. 定义目标参数

先明确总样本量、各维度的比例要求:

total_samples = 100000
# OCCUPA_ID 各取值的占比与对应样本量
occupa_proportions = {2705: 0.7, 2708: 0.2, 2712: 0.1}
occupa_targets = {k: int(total_samples * v) for k, v in occupa_proportions.items()}
# DIG_LABEL 各取值的占比(需应用到每个OCCUPA_ID分组内)
dig_label_proportions = {1: 0.5, 2: 0.2, 7: 0.3}

2. 计算交叉组合的目标抽样量

对每个OCCUPA_ID分组,再按DIG_LABEL的比例拆分目标数量:

# 生成所有交叉组合的目标抽样字典
target_counts = {}
for occupa_id, occ_total in occupa_targets.items():
    for dig_label, dig_ratio in dig_label_proportions.items():
        target_counts[(occupa_id, dig_label)] = int(occ_total * dig_ratio)

比如(2705, 1)的目标量是70000 * 0.5 = 35000,(2708,7)的目标量是20000 * 0.3 = 6000,以此类推。

3. 按交叉组合分组抽样

使用PySpark的groupBy结合applyInPandas实现分组抽样:

from pyspark.sql.functions import struct

def sample_group(df):
    # 获取当前组的OCCUPA_ID和DIG_LABEL
    group_key = (df['OCCUPA_ID'].iloc[0], df['DIG_LABEL'].iloc[0])
    target = target_counts.get(group_key, 0)
    # 如果组内数据量不足目标,直接取全部;否则随机抽样
    if len(df) <= target:
        return df
    else:
        return df.sample(n=target, random_state=42)

# 按OCCUPA_ID和DIG_LABEL分组,应用抽样函数
sampled_df = df.groupBy(struct("OCCUPA_ID", "DIG_LABEL")).applyInPandas(
    sample_group,
    schema=df.schema
)

4. 验证抽样结果

可以通过以下代码检查抽样后的比例是否符合要求:

# 检查OCCUPA_ID比例
sampled_df.groupBy("OCCUPA_ID").count().withColumn(
    "proportion", (sampled_df.groupBy("OCCUPA_ID").count()["count"] / total_samples)
).show()

# 检查DIG_LABEL比例
sampled_df.groupBy("DIG_LABEL").count().withColumn(
    "proportion", (sampled_df.groupBy("DIG_LABEL").count()["count"] / total_samples)
).show()

注意事项

  • 如果某个交叉组合的原始数据量小于目标抽样量,会直接取该组合的全部数据,最终总样本量可能略小于10万,可根据实际需求调整(比如从其他组合补充,或放宽比例要求)
  • 设置random_state是为了保证抽样结果可复现,可根据需要调整
  • 对于百万级数据,applyInPandas的性能完全够用,若数据量极大可考虑RDD层面的操作

内容的提问来源于stack exchange,提问作者Deivid

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 06:41:19