想象一下我有一些具有一定数量级别的数据框:
x1 x2 ... xi Level
1 1 1 1 A
2 2 2 4 A
3 1 4 2 B
. . . . B
. . . . B
. . . . C
. . . . C
. . . . C
我正在尝试以所有级别具有n行的方式对数据帧进行子集化,其中n是具有较少实例的级别的行数。在上面的示例中,A是人口较少的级别(2行),因此所需的输出是:
x1 x2 ... xi Level
1 1 1 1 A
2 2 2 4 A
3 1 4 2 B
. . . . B
. . . . C
. . . . C
级别和行的数量是可变的,因此有必要每次检查具有较少行的级别。此外,例如,如果我有以下条件,则需要以(伪)随机方式选择每个级别的n行:
x1 x2 ... xi Level
1 1 1 1 A
. . . . .
. . . . .
. . . . .
10 1 2 3 C
11 3 2 1 C
12 2 1 3 C
13 3 1 2 C
14 2 3 1 C
并且n = 3,我想避免选择C级的前三行(10,11,12)。 预先感谢。
答案 0 :(得分:2)
以下解决方案仅使用基数R。
n <- min(tapply(Level, Level, length))
inx <- unlist(tapply(seq_along(Level), Level, FUN = function(x) sample(x, n)))
dat[inx, ]
# x Level
#2 0.414641434 A
#3 -1.539950042 A
#5 -0.294720447 B
#6 -0.005767173 B
#9 -0.799009249 C
#8 0.763593461 C
#14 0.252223448 D
#11 -0.289461574 D
#16 0.435683299 E
#17 -1.237538422 E
我已经留下了这样的行名,以表明它们不是连续选择的。如果以后需要连续的行名,请
sel <- dat[inx, ]
row.names(sel) <- NULL
数据。
set.seed(1)
s <- sample(2:5, 5, TRUE)
Level <- sapply(1:5, function(i) rep(LETTERS[i], each = s[i]))
Level <- factor(unlist(Level))
dat <- data.frame(x = rnorm(length(Level)), Level)
答案 1 :(得分:2)
data.table
解决方案。 dat[, .N, Level]
给出每个Levels
组的行数,然后min(N)
,即minN
是最小的行数。下一行是每个组的minN
行中的前排。
library(data.table)
setDT(dat)
minN <- dat[, .N, Level][, min(N)]
dat[, head(.SD, minN), Level]
# Level x
# 1: A 1.2724293
# 2: A 0.4146414
# 3: B -0.9285670
# 4: B -0.2947204
# 5: C 2.4046534
# 6: C 0.7635935
# 7: D -0.2894616
# 8: D -0.2992151
# 9: E 0.4356833
# 10: E -1.2375384
如果要选择随机行,可以混合使用dplyr
和data.table
library(dplyr)
dat[, sample_n(.SD, minN), Level]
或者在arg0naut的评论中使用解决方案
dat[, .SD[sample(.N, minN)], by = Level]
如果您愿意为了速度而牺牲一些可读性,那么另一个选择是
dat[dat[, sample(.I, minN), Level]$V1]
使用的数据(来自Rui Barradas的回答)
set.seed(1)
s <- sample(2:5, 5, TRUE)
Level <- sapply(1:5, function(i) rep(LETTERS[i], each = s[i]))
Level <- factor(unlist(Level))
dat <- data.frame(x = rnorm(length(Level)), Level)
答案 2 :(得分:1)
这是一个dplyr
解决方案:
library(dplyr)
df %>% group_by(Level) %>% ## group by level
mutate(count = n()) %>% ## count number of rows for each group
ungroup() %>%
mutate(count = min(count)) %>% ## select the minimal number of rows
group_by(Level) %>% ## group again to get X rows for each group
slice(sample(1:n(), min(count))) %>% ## get the X random rows
ungroup() %>%
select(-count) ## remove the added count variable
答案 3 :(得分:1)
使用dplyr
进行随机化的sample_frac
方法:
library(dplyr)
df %>%
add_count(Level) %>%
mutate(
n = min(n)
) %>%
group_by(Level) %>%
sample_frac(1) %>%
slice(1:n) %>%
select(-n)