Python 如何根据跨多个列定义的值比例重新平衡数据集?

Python 如何根据跨多个列定义的值比例重新平衡数据集?,python,pandas,scikit-learn,Python,Pandas,Scikit Learn,我有一个如下所示的表(示例行): 该表有数千个实例,它们有三种不同的颜色(绿色、蓝色、黄色)、三种不同的大小(小、中、大)和三种不同的年龄(年轻、中年、老年) 我还为每列设置了一组预定义的百分比/比例。例如: 颜色: 30%蓝色,40%绿色,30%黄色 尺寸: 25%小型,50%中型,25%大型 年龄: 45%年轻人,45%中年人,10%老年人 我的问题是:如何创建符合上述比例的最大数据集 我认为欠采样技术(即删除权重过高的行)似乎是前进的方向,但我发现事情很困难,因为每一行都会影响我控制的所有

我有一个如下所示的表(示例行):

该表有数千个实例,它们有三种不同的颜色(绿色、蓝色、黄色)、三种不同的大小(小、中、大)和三种不同的年龄(年轻、中年、老年)

我还为每列设置了一组预定义的百分比/比例。例如:

  • 颜色: 30%蓝色,40%绿色,30%黄色

  • 尺寸: 25%小型,50%中型,25%大型

  • 年龄: 45%年轻人,45%中年人,10%老年人

  • 我的问题是:如何创建符合上述比例的最大数据集

    我认为欠采样技术(即删除权重过高的行)似乎是前进的方向,但我发现事情很困难,因为每一行都会影响我控制的所有三个变量

    最终结果将是符合上述定义比例的最大数据集


    谢谢大家!

    您需要以与该行的值权重乘积成比例的概率对每行进行采样。这更容易用一个例子来说明

    N = 100000
    
    # generate N samples of each category; "Color" is sampled non-uniformly to 
    # illustrate how to account for prior distribution
    df = pd.DataFrame({
        'Color': np.random.choice(['blue', 'green', 'yellow'], N, p=[0.9, 0.05, 0.05]),
        'Size': np.random.choice(['small', 'medium', 'large'], N),
        'Age': np.random.choice(['young', 'middle-age', 'old'], N),
    })
    
    # target value distribution (e.g., in the final data set, we want 30% blue,
    # 40% green, 30% yellow)
    target_weights = {
        'Color': pd.Series({'blue': 30, 'green': 40, 'yellow': 30}),
        'Size': pd.Series({'small': 25, 'medium': 50, 'large': 25}),
        'Age': pd.Series({'young': 45, 'middle-age': 45, 'old': 10}),
    }
    
    首先,通过先验分布进行归一化。直观地说,您希望采样的概率与目标值频率与先前值频率的比率成正比

    target_weights['Color'] /= df.Color.value_counts()
    target_weights['Size'] /= df.Size.value_counts()
    target_weights['Age'] /= df.Age.value_counts()
    
    然后,计算每行的采样概率

    sample_prob = (
        df.Color.map(target_weights['Color']) *
        df.Size.map(target_weights['Size']) *
        df.Age.map(target_weights['Age'])
    )
    sample_prob.head()
    
    0 3.354744e-10
    1 6.184742e-09
    2.3.390995e-10
    3.396480e-10
    4.6.647330e-10
    数据类型:64
    
    此时,以概率对
    sample\u prob
    中的每一行进行采样将产生所需的分布。按常量缩放采样概率仍将生成目标分布。为了获得最大可能的样本,请确保始终对具有最大采样概率的行进行采样,即:

    sample_prob /= sample_prob.max()
    
    然后,以相应的概率对每一行进行采样

    df_sampled = df.loc[np.random.random(df.shape[0]) < sample_prob]
    
    绿色0.400585
    黄色0.304341
    蓝色0.295074
    名称:颜色,数据类型:float64
    
    df_采样.大小.值_计数(normalize=True)
    
    medium 0.497805
    大号0.253130
    小0.249065
    名称:Size,数据类型:float64
    
    df_sampled = df.loc[np.random.random(df.shape[0]) < sample_prob]
    
    df_sampled.Color.value_counts(normalize=True)