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

在R中不重排数据框实现数据平衡的方法及被删行号定位

问题与解决方案

问题描述

原始数据集:

df <- data.frame(
  "stim" = c("face", "object", "pareidolia", "face", "face", "object", "pareidolia", "object"),
  "RT" = c(23, 24, 25, 26, 27, 22, 25, 23),
  "Opac" = c(70, 60, 80, 65, 60, 61, 59, 70)
)

目标是让每个stim分组的样本数相等,尝试了以下dplyr代码:

library(dplyr)

newdf <- df %>%
  mutate(mn = min(table(stim))) %>%
  group_by(stim) %>%
  sample_n(mn[1]) %>%
  ungroup()

但代码会打乱原始数据顺序:

  • 期望输出(按原始顺序保留各分组的前N条,N为最小分组数):
stim        RT Opac
face        23   70
object      24   60
pareidolia  25   80
face        26   65
object      22   61
pareidolia  25   59
  • 实际输出(分组内聚合,顺序被打乱):
stim        RT Opac
face        23   70
face        26   65
object      24   60
object      22   61
pareidolia  25   80
pareidolia  25   59

同时需要解决附加问题:如何确定被裁剪数据的行号?


解决方案

1. 保持原始顺序的分组下采样

核心思路是给每个分组内的行编号,筛选出编号≤最小分组数的行,最后按原始行号排序:

library(dplyr)

# 计算最小分组样本数
min_count <- df %>% count(stim) %>% pull(n) %>% min()

newdf <- df %>%
  mutate(row_id = row_number()) %>%  # 保留原始行号
  group_by(stim) %>%
  mutate(group_row = row_number()) %>%  # 分组内按原始顺序编号
  filter(group_row <= min_count) %>%  # 筛选每个分组的前min_count条
  ungroup() %>%
  arrange(row_id) %>%  # 还原原始数据顺序
  select(-row_id, -group_row)  # 移除辅助列

print(newdf)

运行后输出会与期望一致,既保证了每个分组样本数相等,又保留了原始数据的顺序。

2. 获取被裁剪的行号

基于上述逻辑,通过对比原始行号与保留行号的差异,即可得到被删除的行编号:

# 先执行预处理保留行号信息
temp_df <- df %>%
  mutate(row_id = row_number()) %>%
  group_by(stim) %>%
  mutate(group_row = row_number()) %>%
  filter(group_row <= min_count) %>%
  ungroup()

# 计算被裁剪的行号
removed_rows <- setdiff(df$row_id, temp_df$row_id)
print(removed_rows)  # 输出:5(对应原始数据中第5行的face,RT=27,Opac=60)

内容的提问来源于stack exchange,提问作者thefriendly_plague.doctor

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 08:03:39