【问题标题】:how can i write from scratch code to do stratified sampling by target variable?我如何从头开始编写代码以按目标变量进行分层抽样?
【发布时间】:2020-12-11 10:12:41
【问题描述】:

所有,我正在尝试从头开始创建(不使用 sklearn 库)以创建 5 个样本(df / 5 的 len),以便每个样本具有与原始数据集相同比例的目标变量(1)。例如原来有 5% 的癌症患者我希望我的 5 个样本中的每一个也有 5% 的目标变量。不知道该怎么做,

df_list=[]
n= round(len(df)/5)
for m in range(1,6):
    m = m*n
    print(df[:m])
    df_list.append(df[:m])

这会创建我想要的每个块,但我现在怎么做才能使目标变量与原始变量的 % 相同?

【问题讨论】:

  • 如您所愿吗?如果是这样,我想我应该得到一个高五。

标签: python pandas sampling imbalanced-data


【解决方案1】:

解决方案:

import numpy as np
import math

def stratify(data, target='y', n=10):
    array = data.values
    y = data[target].values
    
    unique, counts = np.unique(data[target].values, return_counts=True)
    new_counts = counts * (n/sum(counts))
    new_counts = fit_new_counts_to_n(new_counts, n)
    
    selected_count = np.zeros(len(unique))
    selected_row_indices = []
    for i in range(array.shape[0]):
        if sum(selected_count) == sum(new_counts):
            break
        cr_target_value = y[i]
        cr_target_index = np.where(unique==cr_target_value)[0][0]
        if selected_count[cr_target_index] < new_counts[cr_target_index]:
            selected_row_indices.append(i)
            selected_count[cr_target_index] += 1
    row_indices_mask = np.array([x in selected_row_indices for x in np.arange(array.shape[0])])
    
    return pd.DataFrame(array[row_indices_mask], columns=data.columns)

实用类:

def fit_new_counts_to_n(new_counts, n):
    decimals = [math.modf(x)[0] for x in new_counts]
    integers = [int(math.modf(x)[1]) for x in new_counts]
    arg_max = np.array(map(np.argmax, decimals))
    sorting_indices =  np.argsort(decimals)[::-1][:n]
    for i in sorting_indices:
        if sum(integers) < n:
            integers[i] += 1
        else:
            break
    return integers

示例用法:

data = [[  3,   0],
        [ 54,   3],
        [  3,   1],
        [ 64,   1],
        [ 65,   0],
        [ 34,   1],
        [ 45,   2],
        [534,   2],
        [ 57,   1],
        [ 64,   3],
        [  5,   1],
        [ 45,   1],
        [546,   1],
        [  4,   2],
        [ 53,   3],
        [345,   2],
        [456,   2],
        [435,   3],
        [545,   1],
        [ 45,   3]]

data = pd.DataFrame(data, columns=['X1', 'y'])

stratified_data = stratify(data, target='y', n=10)

结果:

      [[  3,   0],
       [ 54,   3],
       [  3,   1],
       [ 64,   1],
       [ 34,   1],
       [ 45,   2],
       [534,   2],
       [ 57,   1],
       [ 64,   3],
       [ 53,   3]]

【讨论】:

  • 谢谢,但是 new count 有什么作用?? counts * (n/sum(counts))
  • np.array([x in selected_row_indices for x in np.arange(20)])
  • 我更改它只是为了尝试,现在更改它应该感谢您的反馈
  • @Maths12 Hi n 是生成的数据框中的新行数。如果您想要分层后的 5 个样本,您可以简单地将 n 设置为 5。new_count 是分层后每个类(目标变量类型)的预期(预期)数字的数组。
  • 谢谢,它可以工作,但速度很慢,基本上我想对我的完整数据集的不断增加的块进行分层抽样,例如如果它的长度为 10,000,我想将它分成增加的间隔,例如第一个是 2000,第二个是 4000,第三个是 6000,依此类推,同时保持班级比例
猜你喜欢
  • 2018-03-22
  • 2023-01-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-22
  • 1970-01-01
  • 2016-12-03
  • 1970-01-01
相关资源
最近更新 更多