从这些问题 - Random sample of rows from subset of an R dataframe& Sample random rows in dataframe我可以很容易地看到如何随机抽样(选择)' n'来自df的行,或者' n'源自df中特定级别因子的行。
以下是一些示例数据:
df <- data.frame(matrix(rnorm(80), nrow=40))
df$color <- rep(c("blue", "red", "yellow", "pink"), each=10)
df[sample(nrow(df), 3), ] #samples 3 random rows from df, without replacement.
例如只需从粉红色&#39;粉红色&#39;中抽取3个随机行颜色 - 使用library(kimisc)
:
library(kimisc)
sample.rows(subset(df, color == "pink"), 3)
或编写自定义函数:
sample.df <- function(df, n) df[sample(nrow(df), n), , drop = FALSE]
sample.df(subset(df, color == "pink"), 3)
但是,我想从因子的每个级别中抽取3(或n)个随机行。即新的df将有12行(蓝色3个,红色3个,黄色3个,粉红色3个)。显然可以多次运行,为每种颜色创建newdf,然后将它们绑定在一起,但我正在寻找一种更简单的解决方案。
答案 0 :(得分:27)
在dplyr
0.3及更高版本的版本中,这很好用:
df %>% group_by(color) %>% sample_n(size = 3)
dplyr
(版本&lt; = 0.2)我开始使用 dplyr 回答这个问题,假设这样可行:
df %.% group_by(color) %.% sample_n(size = 3)
但事实证明,在0.2中存在sample_n.grouped_df
S3方法,但未在NAMESPACE文件中注册,因此永远不会调度它。相反,我必须这样做:
df %.% group_by(color) %.% dplyr:::sample_n.grouped_df(size = 3)
Source: local data frame [12 x 3]
Groups: color
X1 X2 color
8 0.66152710 -0.7767473 blue
1 -0.70293752 -0.2372700 blue
2 -0.46691793 -0.4382669 blue
32 -0.47547565 -1.0179842 pink
31 -0.15254540 -0.6149726 pink
39 0.08135292 -0.2141423 pink
15 0.47721644 -1.5033192 red
16 1.26160230 1.1202527 red
12 -2.18431919 0.2370912 red
24 0.10493757 1.4065835 yellow
21 -0.03950873 -1.1582658 yellow
28 -2.15872261 -1.5499822 yellow
据推测,这将在未来的更新中修复。
答案 1 :(得分:7)
我会考虑my stratified
function,它目前作为GitHub Gist托管。
获取:
library(devtools) ## To download "stratified"
source_gist("https://gist.github.com/mrdwab/6424112")
并将其用于:
stratified(df, "color", 3)
有几种不同的功能可以方便分层采样。例如,您也可以采取“即时”样本。
stratified(df, "color", 3, select = list(color = c("blue", "red")))
为了让您了解该功能的作用,以下是stratified
的参数:
df
:输入data.frame
group
:构成“分层”的一列或多列的字符向量。size
:所需的样本量。
size
的值小于1,则从每个层中采集一个比例样本。size
是1或更大的单个整数,则从每个层中获取该样本数。size
是整数向量,则为每个层获取指定数量的样本。建议您使用命名向量。例如,如果您有两个层次,“A”和“B”,并且您想要“A”中的5个样本和“B”中的10个样本,则应输入size = c(A = 5, B = 10)
。select
:这允许您在采样过程中对组进行子集化。这是list
。例如,如果您的group
变量是“Group”,并且它包含三个层次,“A”,“B”和“C”,但您只想从“A”和“C”进行采样,您可以使用select = list(Group = c("A", "C"))
。replace
:对于替换品抽样。答案 2 :(得分:6)
这是一个解决方案。我们将data.frame拆分为颜色组。然后我们从每组中抽取3行。这会生成一个data.frames列表。
df2 <- lapply(split(df, df$color),
function(subdf) subdf[sample(1:nrow(subdf), 3),]
)
为了获得所需的结果,我们将data.frames列表合并为1 data.frame:
do.call('rbind', df2)
## X1 X2 color
## blue.3 -1.22677188 1.25648082 blue
## blue.4 -0.54516686 -1.94342967 blue
## blue.1 0.44647071 0.16283326 blue
## pink.40 0.23520296 -0.40411906 pink
## pink.34 0.02033939 -0.32321309 pink
## pink.33 -1.01790533 -1.22618575 pink
## red.16 1.86545895 1.11691250 red
## red.11 1.35748078 -0.36044728 red
## red.13 -0.02425645 0.85335279 red
## yellow.21 1.96728782 -1.81388110 yellow
## yellow.25 -0.48084967 0.07865186 yellow
## yellow.24 -0.07056236 -0.28514125 yellow
答案 3 :(得分:5)
您可以使用ave
为具有特定因子级别的每个元素分配随机ID。然后,您可以选择特定范围内的所有随机ID。
rndid <- with(df, ave(X1, color, FUN=function(x) {sample.int(length(x))}))
df[rndid<=3,]
这样做的好处是可以保留原始行顺序和行名称,如果你感兴趣的话。还可以重复使用rndid
向量来相当容易地创建不同长度的子集。
答案 4 :(得分:0)
这是从根本上允许多个组并进行替换采样的方法:
n <- 3
resample <- TRUE
index <- 1:nrow(df)
fun <- function(x) sample(x, n, replace = resample)
a <- aggregate(index, by = list(group = df$color), FUN = fun )
df[c(a$x),]
要添加另一个组,请将其包含在“ by”参数中以进行汇总。