如何使用 Python 进行随机分层抽样(不是训练/测试拆分)?
Posted
技术标签:
【中文标题】如何使用 Python 进行随机分层抽样(不是训练/测试拆分)?【英文标题】:How to do a random stratified sampling with Python (Not a train/test split)? 【发布时间】:2018-10-16 03:17:42 【问题描述】:我正在寻找进行随机分层抽样(如调查和民意调查)的最佳方式。我不想做 sklearn.model_selection.StratifiedShuffleSplit 因为我没有做监督学习而且我没有目标。我只想从 pandas DataFrame (https://www.investopedia.com/terms/stratified_random_sampling.asp) 创建随机分层样本。
Python 是我的主要语言。
感谢您的帮助
【问题讨论】:
您的问题中的“我希望样本尽可能地代表我的人口”似乎使它成为一个非常难以解决的问题,因此对于***来说太宽泛了...... 查看pandas.DataFrame.sample()
您可能需要先弄清楚这个问题的统计部分(更准确地描述您需要实施的抽样程序)并描述您拥有的数据(您有完整的人口数据吗?加权调查数据?),在此之前将在本网站的范围内。
谢谢 sacul。我发现它非常方便,并在我的解决方案中使用了它。
【参考方案1】:
鉴于变量是分箱的,下面的一行应该会给你想要的输出。我看到 scikit-learn 主要用于您以外的目的,但使用其中的函数应该不会造成任何伤害。
请注意,如果您的 scikit-learn 版本早于 0.19.0,则采样结果可能包含重复行。
如果您测试以下方法,请分享它的行为是否符合预期。
from sklearn.model_selection import train_test_split
stratified_sample, _ = train_test_split(population, test_size=0.999, stratify=population[['income', 'sex', 'age']])
【讨论】:
我自己测试了这个。不幸的是,这没有所需的行为。由于它的设计目的是使整个训练集和测试集的相对频率保持相同,因此它并不专注于使单个集内的频率相等。你可以阅读更多here 我找到了一个可行的解决方案here。【参考方案2】:这是迄今为止我最好的解决方案。重要的是在之前对连续变量进行分箱,并为每个层提供最少的观测值。
在这个例子中,我是:
-
产生人口
以纯随机方式采样
随机分层抽样
在比较两个样本时,分层样本更能代表总体。
如果有人知道更优化的方法,请随时分享。
import pandas as pd
import numpy as np
# Generate random population (100K)
population = pd.DataFrame(index=range(0,100000))
population['income'] = 0
population['income'].iloc[39000:80000] = 1
population['income'].iloc[80000:] = 2
population['sex'] = np.random.randint(0,2,100000)
population['age'] = np.random.randint(0,4,100000)
pop_count = population.groupby(['income', 'sex', 'age'])['income'].count()
# Random sampling (100 observations out of 100k)
random_sample = population.iloc[
np.random.randint(
0,
len(population),
int(len(population) / 1000)
)
]
# Random Stratified Sampling (100 observations out of 100k)
stratified_sample = list(map(lambda x : population[
(
population['income'] == pop_count.index[x][0]
)
&
(
population['sex'] == pop_count.index[x][1]
)
&
(
population['age'] == pop_count.index[x][2]
)
].sample(frac=0.001), range(len(pop_count))))
stratified_sample = pd.concat(stratified_sample)
【讨论】:
以上是关于如何使用 Python 进行随机分层抽样(不是训练/测试拆分)?的主要内容,如果未能解决你的问题,请参考以下文章
基于 python 中的多个特征的训练测试拆分的分层交叉验证或抽样