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

基于列分布与条件的Python DataFrame随机数据采样方法

多列分布约束+高频城市优先的随机采样方案

核心逻辑:常规pandas单维度分层采样无法同时满足多列分布要求,需要先计算两列的采样配额,再结合City频次权重做约束采样,适配百万级数据规模的性能要求。


实现步骤

  • 步骤1:统计全量数据中Id、Fruit列的分布占比,换算为指定采样量下各分组的目标采样条数,校验总条数匹配
  • 步骤2:统计每个City的全量出现频次,作为该行的采样权重,频次越高权重越大
  • 步骤3:采用约束采样逻辑,同时对齐Id、Fruit的采样配额,优先抽取权重更高的行

可运行代码实现

1. 基础数据准备

import pandas as pd
import numpy as np

# 示例输入数据,可替换为百万级全量数据
input_data = pd.DataFrame({
    'Id': ['A','A','A','A','A','A','B','B','B','C','C','C'],
    'Fruit': ['Apple','Mango','Orange','Apple','Apple','Mango','Apple','Mango','Apple','Apple','Apple','Orange'],
    'City':['California','California','Chicago','Michigan','New York','Ohio','Michigan','Michigan','Ohio','Florida','New York','Washington']
})

# 定义采样总条数
sample_n = 4

2. 计算各列采样配额

# 计算Id列各分组目标采样数
id_dist = input_data['Id'].value_counts(normalize=True).sort_index()
id_target = (id_dist * sample_n).round().astype(int)
# 校验总和匹配
if id_target.sum() != sample_n:
    diff = sample_n - id_target.sum()
    id_target[id_target.idxmax()] += diff

# 计算Fruit列各分组目标采样数
fruit_dist = input_data['Fruit'].value_counts(normalize=True).sort_index()
fruit_target = (fruit_dist * sample_n).round().astype(int)
if fruit_target.sum() != sample_n:
    diff = sample_n - fruit_target.sum()
    fruit_target[fruit_target.idxmax()] += diff

# 计算City权重:出现频次越高权重越大
city_freq = input_data['City'].value_counts().to_dict()
input_data['weight'] = input_data['City'].map(city_freq)

3. 确定性优先采样(优先取最高频City的行)

适合需要固定优先级的场景,性能最高:

# 按权重倒序排序,优先取高频City行
input_data_sorted = input_data.sort_values('weight', ascending=False, ignore_index=True)
id_count = {k:0 for k in id_target.index}
fruit_count = {k:0 for k in fruit_target.index}
result = []

for _, row in input_data_sorted.iterrows():
    curr_id, curr_fruit = row['Id'], row['Fruit']
    if id_count[curr_id] < id_target[curr_id] and fruit_count[curr_fruit] < fruit_target[curr_fruit]:
        result.append(row)
        id_count[curr_id] += 1
        fruit_count[curr_fruit] += 1
    if len(result) == sample_n:
        break

output_data = pd.DataFrame(result).drop(columns='weight').reset_index(drop=True)

4. 随机加权采样(兼顾随机性+高频优先)

符合随机采样要求,高频City被抽中的概率更高:

id_count = {k:0 for k in id_target.index}
fruit_count = {k:0 for k in fruit_target.index}
remaining_data = input_data.copy()
result = []

for _ in range(sample_n):
    # 过滤剩余满足配额的候选行
    mask = (remaining_data['Id'].map(id_count) < id_target[remaining_data['Id']]) & \
           (remaining_data['Fruit'].map(fruit_count) < fruit_target[remaining_data['Fruit']])
    candidates = remaining_data[mask]
    # 按City权重加权随机采样1行
    sampled_row = candidates.sample(n=1, weights=candidates['weight']).iloc[0]
    result.append(sampled_row)
    # 更新计数器和剩余数据集
    id_count[sampled_row['Id']] += 1
    fruit_count[sampled_row['Fruit']] += 1
    remaining_data = remaining_data.drop(sampled_row.name)

output_data = pd.DataFrame(result).drop(columns='weight').reset_index(drop=True)

性能说明

两种实现的时间复杂度均为O(nlogn),百万行数据可在秒级完成运算,无额外性能依赖。

内容的提问来源于stack exchange,提问作者Dr.Chuck

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 04:09:05