How to do a random stratified sampling with Python (Not a train/test split)?

问题描述 投票:0回答:3

我正在寻找进行随机分层抽样(如调查和民意调查)的最佳方法。我不想做 sklearn.model_selection.StratifiedShuffleSplit 因为我没有做监督学习而且我没有目标。我只想从 pandas DataFrame (https://www.investopedia.com/terms/stratified_random_sampling.asp) 创建随机分层样本。

Python 是我的主要语言。

感谢您的帮助

python pandas numpy sampling
3个回答
10
投票

鉴于变量已分箱,下面的一个衬里应该会为您提供所需的输出。我看到 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']])

4
投票

这是我迄今为止最好的解决方案。重要的是在之前对连续变量进行分箱,并对每个层进行最少的观察。

在这个例子中,我是:

  1. 生成人口
  2. 纯随机抽样
  3. 随机分层抽样

比较两个样本时,分层样本更能代表总体。

如果有人有更好的方法,请随时分享。


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)

0
投票

您可以在没有 scikit-learn 的情况下使用类似于此的函数来执行此操作:

import pandas as pd
import numpy as np

def stratified_sampling(df, strata_col, sample_size):
    groups = df.groupby(strata_col)
    sample = pd.DataFrame()
    
    for _, group in groups:
        stratum_sample = group.sample(frac=sample_size, replace=False, random_state=7)
        sample = sample.append(stratum_sample)
    
    return sample

在上面:

  • df 是要采样的 DataFrame
  • strata_col 是表示感兴趣的层(例如“性别”)的列
  • sample_size 是所需的样本大小(例如 0.2 代表 20% 的数据)

然后您可以按如下方式调用

stratified_sampling

sample = stratified_sampling(df_to_be_sampled, 'gender', 0.2)

这将返回一个名为 sample 的新 DataFrame,其中包含随机采样的数据。请注意,我选择了

random_state=7
进行测试和再现性,但这当然是任意的。

© www.soinside.com 2019 - 2024. All rights reserved.