首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何根据多列中定义的值比例重新平衡数据集?

如何根据多列中定义的值比例重新平衡数据集?
EN

Stack Overflow用户
提问于 2019-10-28 20:53:00
回答 1查看 178关注 0票数 1

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

代码语言:javascript
复制
|---------------------|------------------|---------------|
|      Color          |       Size       |        Age    |
|---------------------|------------------|---------------|
|       Green         |       Small      |       Young   |
|---------------------|------------------|---------------|

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

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

  1. 颜色: 30%蓝色,40%绿色,30%黄色
  2. 大小: 25%小,50%中等,25%大
  3. 年龄: 45%年轻,45%中年,10%老年

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

我认为,一种欠采样技术(即丢弃具有过加权值的行)似乎是前进的道路,但我发现这很困难,因为每一行都会影响到我控制的所有三个变量。

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

谢谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-10-29 05:27:08

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

代码语言:javascript
复制
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}),
}

第一,通过先验分布来规范。直观地,您希望以与目标值频率与先验值频率之比成比例的概率进行采样。

代码语言:javascript
复制
target_weights['Color'] /= df.Color.value_counts()
target_weights['Size'] /= df.Size.value_counts()
target_weights['Age'] /= df.Age.value_counts()

然后,计算每一行的抽样概率。

代码语言:javascript
复制
sample_prob = (
    df.Color.map(target_weights['Color']) *
    df.Size.map(target_weights['Size']) *
    df.Age.map(target_weights['Age'])
)
sample_prob.head()
代码语言:javascript
复制
0    3.354744e-10
1    6.184742e-09
2    3.390995e-10
3    3.396480e-10
4    6.647330e-10
dtype: float64

此时,对df中的每一行进行概率sample_prob抽样将产生所需的分布。用常数对采样概率进行缩放仍然会产生目标分布。为了获得尽可能大的样本,确保具有最大抽样概率的行总是被采样,即,

代码语言:javascript
复制
sample_prob /= sample_prob.max()

然后,用相应的概率对每一行进行抽样。

代码语言:javascript
复制
df_sampled = df.loc[np.random.random(df.shape[0]) < sample_prob]

您可以验证发行版是否正确:

代码语言:javascript
复制
df_sampled.Color.value_counts(normalize=True)
代码语言:javascript
复制
green     0.400585
yellow    0.304341
blue      0.295074
Name: Color, dtype: float64
代码语言:javascript
复制
df_sampled.Size.value_counts(normalize=True)
代码语言:javascript
复制
medium    0.497805
large     0.253130
small     0.249065
Name: Size, dtype: float64
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58598262

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档