如何用Python对含ID与性别的数据集实现Disproportional Stratified Sampling组建团队?
非比例分层抽样组建团队的Python实现
第一步:修正数据读取代码
你的原代码存在变量名错误(inc、onc应为gr、gend),先修正这段代码以正确获取各分层的人数分布:
from openpyxl import load_workbook wb = load_workbook("dataset.xlsx") sh = wb["Page"] dist = [] # 遍历415条数据行 for i in range(415): gr = sh[f'C{i+1}'].value # 分配ID(1-8) gend = sh[f'D{i+1}'].value # 性别(M/F) dist.append(f"{int(gr)}{gend}") # 输出各分层人数统计 for grade in range(1, 9): male_count = dist.count(f"{grade}M") female_count = dist.count(f"{grade}F") print(f"分配ID {grade} 男性人数: {male_count}") print(f"分配ID {grade} 女性人数: {female_count}")
第二步:实现非比例分层抽样
非比例分层抽样的核心是不按原分层比例分配样本量,而是根据需求自定义每个分层的抽取数量(比如给小群体分配更多样本以保证代表性)。下面用pandas+sklearn实现高效抽样:
1. 导入数据为DataFrame
import pandas as pd # 读取Excel数据,指定列名简化后续操作 df = pd.read_excel("dataset.xlsx", sheet_name="Page", usecols=["C", "D"], names=["分配ID", "性别"]) df["分配ID"] = df["分配ID"].astype(int) # 确保分配ID为整数类型
2. 定义各分层的抽样数量
根据团队需求指定每个(分配ID, 性别)分层要抽取的人数,示例中给每个分层固定抽5人:
sample_sizes = { (1, "M"): 5, (1, "F"): 5, (2, "M"): 5, (2, "F"): 5, (3, "M"): 5, (3, "F"): 5, (4, "M"): 5, (4, "F"): 5, (5, "M"): 5, (5, "F"): 5, (6, "M"): 5, (6, "F"): 5, (7, "M"): 5, (7, "F"): 5, (8, "M"): 5, (8, "F"): 5, }
3. 执行抽样
from sklearn.model_selection import StratifiedShuffleSplit # 创建分层标识列,用于区分不同分层 df["分层标识"] = df["分配ID"].astype(str) + df["性别"] sampled_df = pd.DataFrame() splitter = StratifiedShuffleSplit(n_splits=1, test_size=None) # 遍历每个分层执行抽样 for strat, size in sample_sizes.items(): strat_id, strat_gender = strat # 筛选当前分层的数据 strat_data = df[(df["分配ID"] == strat_id) & (df["性别"] == strat_gender)] if len(strat_data) >= size: # 随机抽取指定数量样本 _, sample_idx = next(splitter.split(strat_data, strat_data["分层标识"])) sampled = strat_data.iloc[sample_idx[:size]] sampled_df = pd.concat([sampled_df, sampled], ignore_index=True) else: # 若分层人数不足,直接纳入全部数据 print(f"警告:分层({strat_id}, {strat_gender})仅{len(strat_data)}人,不足{size}人,已全部纳入样本") sampled_df = pd.concat([sampled_df, strat_data], ignore_index=True) # 输出抽样结果并保存 print("抽样后的团队数据:") print(sampled_df) sampled_df.to_excel("抽样团队.xlsx", index=False)
关键说明
- 你可以根据实际需求调整
sample_sizes字典,比如给人数较少的分层分配更多样本,或针对特定分层调整抽取数量。 - 若不想依赖
sklearn,可直接用pandas的sample方法:对每个分层调用strat_data.sample(n=size, random_state=42)(random_state保证抽样结果可复现)。 - 用
pandas读取数据无需硬编码行数,适配数据量变化更灵活。
内容的提问来源于stack exchange,提问作者As Per
相关产品推荐
相关产品推荐

