You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何移除随机样本使数据框中各国家Gender组比例匹配?

按国家匹配Gender样本量的实现方法

问题背景

现有一个包含国家和性别数据的dataframe,当前Gender与COUNTRY的交叉表如下:

> table(df$Gender , df$COUNTRY)
   
      1   2   3
  0  86  81 282
  1  21   7  23

需要将每个国家内Gender=0的样本量缩减到与Gender=1的样本量一致,最终期望的交叉表为:

> table(df$Gender , df$COUNTRY)
   
      1   2   3
  0  21   7  23
  1  21   7  23

一、手动实现方法

核心逻辑:按COUNTRY分组,对每个组内的Gender=0样本随机抽取与Gender=1相同的数量,再合并两类样本。

方法1:用tidyverse工具链实现

# 设置随机种子保证结果可重复
set.seed(123)

library(dplyr)

balanced_df <- df %>%
  group_by(COUNTRY) %>%
  group_modify(function(.x, .y) {
    # 获取当前组内Gender=1的样本量
    n_gender1 <- sum(.x$Gender == 1)
    # 筛选Gender=1的样本
    gender1 <- .x %>% filter(Gender == 1)
    # 从Gender=0的样本中随机抽取n_gender1条
    gender0_sample <- .x %>% filter(Gender == 0) %>% sample_n(n_gender1)
    # 合并两类样本
    bind_rows(gender1, gender0_sample)
  }) %>%
  ungroup()

# 验证结果
table(balanced_df$Gender, balanced_df$COUNTRY)

方法2:用基础R实现

set.seed(123)

balanced_list <- list()
countries <- unique(df$COUNTRY)

for (cntry in countries) {
  # 筛选当前国家的数据
  cntry_data <- df[df$COUNTRY == cntry, ]
  # 计算Gender=1的样本数量
  n1 <- sum(cntry_data$Gender == 1)
  # 提取Gender=1的样本
  g1 <- cntry_data[cntry_data$Gender == 1, ]
  # 随机抽取对应数量的Gender=0样本
  g0_idx <- sample(which(cntry_data$Gender == 0), n1)
  g0 <- cntry_data[g0_idx, ]
  # 合并后存入列表
  balanced_list[[as.character(cntry)]] <- rbind(g1, g0)
}

# 合并所有组的结果
balanced_df <- do.call(rbind, balanced_list)
rownames(balanced_df) <- NULL

# 验证结果
table(balanced_df$Gender, balanced_df$COUNTRY)

二、使用R包实现

可以用caret包的downSample函数快速完成下采样(缩减多数类样本量到少数类水平),无需手动写循环。

步骤:

  1. 安装并加载包
install.packages("caret")
library(caret)
library(dplyr)
  1. 分组应用下采样
set.seed(123)

balanced_df <- df %>%
  group_by(COUNTRY) %>%
  group_modify(function(.x, .y) {
    # 将Gender转为因子(downSample要求响应变量为因子)
    .x$Gender <- as.factor(.x$Gender)
    # 执行下采样,自动将多数类(Gender=0)缩减到少数类(Gender=1)的数量
    downsampled <- downSample(x = .x[, !names(.x) %in% "Gender"], y = .x$Gender)
    # 还原Gender为数值型(按需选择)
    downsampled$Class <- as.numeric(as.character(downsampled$Class))
    # 重命名列名回原名称
    colnames(downsampled)[colnames(downsampled) == "Class"] <- "Gender"
    downsampled
  }) %>%
  ungroup()

# 验证结果
table(balanced_df$Gender, balanced_df$COUNTRY)

数据集dput

df <- structure(list(Gender = c(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
                                0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
                                0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 
                                1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 
                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
                                1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 
                                0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
                                0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 
                                0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
                                1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 
                                0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 
                                0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
                                0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 
                                1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 
                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
                                0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 
                                1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 
                                0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 
                                0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
                                0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
                                0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
                                1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 
                                0, 1, 1, 0, 0), COUNTRY = c(2, 3, 2, 1, 3, 3, 3, 2, 2, 3, 3, 
                                                            3, 3, 3, 3, 2, 3, 3, 1, 3, 3, 3, 3, 1, 2, 3, 2, 3, 1, 3, 2, 3, 
                                                            3, 3, 2, 2, 3, 3, 3, 2, 3, 2, 2, 1, 3, 3, 3, 2, 2, 3, 1, 1, 2, 
                                                            2, 1, 3, 3, 1, 2, 1, 3, 3, 3, 1, 1, 3, 3, 3, 1, 3, 2, 1, 3, 2, 
                                                            3, 3, 2, 3, 3, 3, 3, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 
                                                            3, 3, 3, 3, 3, 3, 3, 3, 2, 3, 3, 3, 1, 1, 1, 1, 3, 1, 2, 1, 3, 
                                                            2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 1, 2, 3, 3, 3, 1, 1, 3, 1, 1, 2, 
                                                            2, 3, 3, 1, 2, 3, 3, 3, 2, 3, 3, 1, 3, 3, 1, 3, 1, 1, 3, 3, 2, 
                                                            3, 1, 1, 1, 3, 3, 3, 2, 3, 3, 2, 3, 2, 1, 3, 2, 3, 1, 3, 2, 2, 
                                                            2, 3, 3, 2, 1, 3, 3, 3, 2, 3, 3, 3, 3, 3, 3, 1, 3, 3, 3, 2, 2, 
                                                            1, 1, 3, 1, 1, 1, 3, 3, 1, 2, 1, 1, 1, 1, 3, 3, 3, 1, 3, 3, 2, 
                                                            3, 3, 3, 3, 3, 1, 3, 3, 2, 1, 1, 2, 3, 2, 3, 3, 3, 2, 2, 3, 3, 
                                                            3, 3, 1, 3, 2, 2, 1, 3, 2, 1, 3, 2, 3, 2, 3, 3, 2, 3, 2, 3, 3, 
                                                            3, 1, 3, 2, 1, 1, 3, 3, 3, 3, 3, 2, 3, 3, 3, 3, 1, 2, 3, 1, 2, 
                                                            3, 2, 1, 2, 1, 3, 1, 3, 3, 3, 3, 3, 1, 3, 1, 1, 3, 1, 3, 1, 1, 
                                                            3, 3, 1, 3, 1, 1, 1, 2, 3, 2, 2, 3, 3, 3, 2, 3, 3, 2, 3, 3, 3, 
                                                            3, 3, 3, 3, 2, 3, 1, 3, 3, 3, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 
                                                            1, 3, 3, 1, 2, 3, 1, 3, 3, 3, 1, 3, 1, 3, 3, 3, 1, 1, 3, 2, 3, 
                                                            1, 3, 3, 3, 1, 2, 3, 3, 3, 3, 1, 3, 1, 3, 1, 1, 3, 3, 3, 3, 1, 
                                                            3, 3, 3, 3, 3, 1, 1, 3, 3, 2, 3, 3, 3, 3, 1, 3, 3, 2, 3, 3, 1, 
                                                            3, 3, 3, 2, 3, 1, 3, 3, 1, 3, 2, 1, 2, 3, 3, 3, 3, 3, 3, 2, 2, 
                                                            2, 3, 3, 2, 3, 3, 1, 3, 3, 3, 3, 3, 3, 3, 2, 1, 3, 3, 3, 3, 3, 
                                                            3, 1, 3, 1, 2, 3, 3, 2, 3, 3, 3, 3, 2, 2, 3, 3, 3, 3, 3, 3, 3, 
                                                            1, 1, 3, 3, 3, 1, 
相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 00:02:33