在数据帧中为每组采样n个随机行

时间:2014-05-23 14:21:37

标签: r random dataframe sample

从这些问题 - 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,然后将它们绑定在一起,但我正在寻找一种更简单的解决方案。

5 个答案:

答案 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”参数中以进行汇总。